middleman-vcs-time で正確な sitemap.xml を出力する

Middleman で Web サイトを作る場合, sitemap.xml の lastmod はビルドされ出力される時刻に統一されてしまいます。

sitemap.xml の仕様を考えると可能な限り lastmod は正しい時刻が望ましいです。現在開発中サービスの都合もあり「どうすれば正確な時刻を出力できるか?」と思い悩んでしばらく時間が経ってしまいました。

Twitter で rubygems middleman で検索して眺めていたところ, この問題を解決してくれそうな拡張機能がひっそりリリースされていることに気づきました。

middleman-vcs-time | RubyGems.org

middleman-vcs-time 概要

README によると,

Provides means to look up the last-modified times of Middleman sitemap resources according to version control. Supports Git with a fallback to filesystem metadata.

README.md: https://github.com/AndrewKvalheim/middleman-vcs-time/blob/master/README.md

とのことで, VCS (Git など) の最終変更時刻をベースに Middleman の sitemap リソースを書き替えてくれるようです。現状では Git をサポートし, フォールバックとしてファイルのメタデータを参照します。とのことで。

sitemap リソースについて

sitemap リソースはドキュメントでいうと サイトマップ のことです。

Middleman は Web サイトデータを出力する前にビルド対象のファイルを収集し, sitemap リソースというデータを用意してからファイル出力を行います。この sitemap リソースは各ページのタイトル, 元ファイルパス, 出力先ファイルパスやら何やらのデータを持っています。この sitemap まわりは拡張機能の開発や凝ったサイト構成にならないと関わらない部分なので難しいです。

この sitemap リソースのうち各ページの更新時刻を VCS ベースに差し替えてくれます。テンプレート側ではこの時刻を使って更新日時を出力することが可能になります。

sitemap.xml でのサンプル

サンプルとして 株式会社フィルインsitemap.xml.builder を挙げます。

priority の取り扱いなど関係ない処理も混ざっているので簡易版として次のコードを参考にしてみてください。

site_url = "https://www.fillin-inc.com"
xml.instruct!
xml.urlset 'xmlns' => "http://www.sitemaps.org/schemas/sitemap/0.9" do
  sitemap.resources.select { |page| page.destination_path =~ /\.html/ }.each do |page|
    xml.url do
      xml.loc URI.escape(File.join(site_url, page.destination_path))
  
      # page.mtime で差し替えられた時刻を取得
      xml.lastmod page.mtime.iso8601

      xml.changefreq "weekly"
      xml.priority "0.5"
    end
  end
end

出力されたコードは https://www.fillin-inc.com/sitemap.xml で確認できます。lastmod の時刻がそれぞれバラバラになっているのが確認できます。