• 作成:

サイトにsitemap.xmlを追加しました, 簡単かと思ったら意外と大変で2時間ぐらいかかりました

動機

昔の記事を更新した時にGoogleに優先してクロールしてほしいため.

Yesodを使った時は動的コンテンツを含んでも yesod-sitemap を使ってサクッと作れたのでかなり簡単な作業だと認識したため.

参考実装

Sitemap with Hakyll を参考に, こちらはテンプレートではなく処理前コードを書きました.

最終的には/sitemap.xmlには

<?xml version="1.0" encoding="utf-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  $for(entry)$
  <url>
    <loc>https://www.ncaq.net$url$</loc>
    <lastmod>$updated$</lastmod>
  </url>
  $endfor$
</urlset>

と書いて,

site.hsには

  create ["sitemap.xml"] $ do
    route idRoute
    let sitemapContext = listField "entry" entryContext (reverse <$> loadAll ("*.md" .||. "entry/*.md"))
    compile $ getResourceBody >>=
      applyAsTemplate sitemapContext >>=
      cleanUrls >>=
      indentXml

を追加しました.

updatedは存在しなくてもファイル名から補完されるのでOK.

Google Search Consoleのチェックにかける

Google Search Consoleにはsitemapをテストする機能があります. これにかけてみましょう. このテスト機能新しいGoogle Search Consoleには無いので, 現状は古い方を使いましょう.

エラーが出ましたね.

タイプミスをしていました

有効な URL ではありません。 修正してから、再送信してください。

と出てきましたが, 実際表示されたURLをクリックするとページが表示されるので首を捻っていました.

よく見てみたらhttps://https:///とスラッシュを1個多く書いてしまうtypoを行っていました. Firefoxが忖度してスラッシュ1つ多くても開いてくれるのでなかなか気がつくことが出来ませんでした.

時刻にタイムゾーンをつけていませんでした

日付の値が無効です。 日付または書式設定を修正してから、再送信してください。

と出てきました. ISO 8601に準拠してるのにどうして…

サイトマップの規格では時刻を付ける場合はタイムゾーンも一緒に付ける必要があるようです.

逆に時刻がついてない場合はタイムゾーンは付けてはいけません. これISO 8601が逆におかしくないですか? 時刻がついていない日付だけのデータでも, タイムゾーンによって意味は変わってくると思うのですが… まあ規格がそうなってるのは仕方がないですね.

mItemDateを以下のように書き換えて,

        mItemDate item = case splitOneOf "-" f of
          [year, month, day, hour, minute, second] ->
            Just $ concat [year, "-", month, "-", day, "T", hour, ":", minute, ":", second, "+09:00"]

updatedを明示的に記事ファイルに書いているものにはタイムゾーンを付けました.

EmacsのISO 8601を挿入する関数も変更です.

(defun insert-iso-datetime ()
  (interactive)
  (insert (format-time-string "%Y-%m-%dT%H:%M:%S%:z" (current-time))))

完了

これでエラーが消えてくれて完了です. 思ったより手間がかかりました…

エラー消滅

クロールはまだ保留中なので本当にクロールしてくれるのかはまだわかりませんが, 少なくともエラーがないsitemap.xmlを作ることが出来ました.