サイトマップは存在するだけでは足りない — indexから辿れることを検査する

  • #Astro
  • #sitemap
  • #静的サイト
  • #テスト

今回やったこと

静的サイトの public/ にサイトマップが置かれていて、HTTP 200 を返していても、検索エンジンがそこへ到達できるとは限らない。今回の焦点は、個々の XML の疎通ではなく、sitemap-index.xml からすべての sitemap が参照されているかを検査することにした。

実害の形は単純だった。Astro 側の sitemap は index から参照されていた一方、静的に配置されたレガシー側の sitemap-legacy.xml は存在していたのに index に含まれていなかった。レガシー側には約2万 URLがあり、ファイル自体は200を返すため、本番 URL をいくつか確認するだけでは漏れが見えない。

ファイルの存在と参照関係を分ける

まず public/ を走査して、静的な sitemap を拾う。src/lib/static-sitemaps.mjsstaticSitemapFiles() は sitemap の種類を区別し、入れ子の sitemap index を通常の urlset として扱わない。次に、生成された sitemap-index.xml の参照先と、実際に public/ にあるファイルを比較する。

public/
├── sitemap-index.xml
├── sitemap-0.xml
└── sitemap-legacy.xml

この例で index が sitemap-0.xml だけを指していれば、sitemap-legacy.xml は「ファイルがあるが、入口から辿れない」状態になる。検査関数 unreferencedSitemaps() はこの差分を返し、未参照のファイルがあれば停止させる。index 自体が無い場合も「漏れ0」とは答えず、検査不能として扱う。

const missing = unreferencedSitemaps(publicDir);
if (missing.length > 0) {
  throw new Error(`index から未参照: ${missing.join(', ')}`);
}

実装上は、sitemap を index に追加する側と、追加漏れを検査する側を同じ設定の流れへ置く。astro.config.mjs では sitemap() の後に assertSitemapsIndexed() が動くこともテストで確認している。生成前に確認すると、まだ存在しない index を見てしまうからだ。

回帰テストで「200なのに漏れる」を固定する

scripts/test_static_sitemaps.mjs には実データの確認と、一時ディレクトリを使った fixture テストがある。正常系では sitemap-0.xmlsitemap-legacy.xml の両方を index が指すことを確認する。異常系では、レガシー sitemap を置いたまま index から外し、未参照として検出する。

状態HTTPだけの確認index到達性の検査
sitemap が無い失敗失敗
sitemap があり200成功に見える参照されなければ失敗
index が全ファイルを参照成功成功
index が無い判定不能判定不能として停止

この差分が必要なのは、疎通と発見可能性が別の性質だからである。ファイルを配信できることは、サイトマップの入口から辿れることを意味しない。静的ファイルを追加する運用では、追加した人が index の編集を忘れるだけで同じ穴が再発する。

自動化する範囲としない範囲

この検査が保証するのは、public/ の静的 sitemap が index から参照されていること、index が存在すること、入れ子の sitemap index を誤って受け入れないことだ。URL の内容が正しいか、重複していないか、検索エンジンが実際に取得できるかまでは別の検査になる。

したがって、サイトマップの数を手で数えて正常と判断するのではなく、配置場所を走査し、入口との関係を機械で比較する。参照漏れが起きたときにビルドを止めることで、200を返す不完全な成果物をそのまま配らずに済む。

参照した実装は src/lib/static-sitemaps.mjsscripts/test_static_sitemaps.mjsastro.config.mjs である。レガシー sitemap の漏れと、修正後の回帰テストの形を整理した。

環境・バージョン: テストは Node.js の組み込み test runner を node --test で実行する構成で、外部サービスへの問い合わせを前提にしない。

更新履歴

  • 2026-09-02: 初稿。リポジトリ内の実装とテスト記録をもとに整理。

訂正履歴

(なし)