ブログ一覧

Astroで理想のサイトマップを自作する

Astroには公式のサイトマップインテグレーション( @astrojs/sitemap )があり、npx astro add sitemapを実行するだけでビルド時にサイトマップが生成されます。静的サイトであれば、基本的にはこれで足ります。

この記事はもともと2023年に、当時のインテグレーションにあった「URLに3桁の数字が含まれるページがサイトマップから除外されるバグ」を回避するために書いたものです。そのバグはすでに修正されているため、現在の視点で「それでもサイトマップを自作したいケース」を整理して書き直しました。

当時のバグは修正済み

2023年当時の@astrojs/sitemapは、ステータスコードページ(404や500)を除外するための正規表現が雑で、/blog/123/のような「3桁の数字で終わるURL」まで巻き添えで除外していました。

const STATUS_CODE_PAGE_REGEXP = /\/[0-9]{3}\/?$/;

この問題は Issue #10778 として報告され、2024年に修正されました。現在は404・500ページだけが正しく除外されるようになっています。当時このブログはWordPress時代のURL構成(/blog/記事ID/)で運用していたため、もろに直撃していました。

いま自作する理由:SSR(オンデマンドレンダリング)

現在、サイトマップを自作する実質的な理由はこれだと思います。

@astrojs/sitemapはビルド時に静的生成されたページからURLを集める仕組みのため、output: "server"で動くSSRサイトでは動的ルートがサイトマップに入りません。CMSと連携してコンテンツをDBから配信しているようなサイトだと、肝心の記事ページが全部漏れることになります。

このブログ自体がまさにその構成(コンテンツはDBにあり、ページはサーバーレンダリング)なので、サイトマップはビルド時ではなくリクエスト時に生成しています。

SSR用サイトマップエンドポイントの作り方

src/pages/sitemap.xml.tsとしてエンドポイントを作るだけです。

import type { APIRoute } from "astro";

export const prerender = false;

const SITE = "https://example.com";

export const GET: APIRoute = async () => {
	// DBやCMSなど、自分のデータソースから公開中のURL一覧を集める
	const posts = await getPublishedPosts();
	const urls = ["/", "/about", ...posts.map((p) => `/posts/${p.slug}`)];

	const xml = [
		`<?xml version="1.0" encoding="UTF-8"?>`,
		`<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">`,
		...urls.map((path) => `	<url><loc>${SITE}${path}</loc></url>`),
		`</urlset>`,
	].join("\n");

	return new Response(xml, {
		headers: {
			"Content-Type": "application/xml; charset=utf-8",
			"Cache-Control": "public, max-age=3600",
		},
	});
};

ポイントは3つです。

  • prerender = falseを指定して、リクエストのたびにサーバーで生成する(コンテンツの追加・削除が即サイトマップに反映される)
  • Cache-Controlを付けて、クローラーのアクセスのたびに毎回DBを叩かないようにする
  • lastmodを出したい場合は、各コンテンツの更新日時を<url>内に足す

あとはrobots.txtSitemap: https://example.com/sitemap.xmlの一行を書いておけば完了です。

静的サイトなら公式インテグレーションで十分

逆に、全ページをビルド時に静的生成しているサイトであれば、いま自作する理由はほぼありません。公式インテグレーションにはfilter(除外設定)やcustomPages(手動追加)といったオプションがあるので、細かい調整もそちらで対応できます。

2023年には「バグを回避するため」という後ろ向きな理由で自作していましたが、2026年現在は「SSRだから自作する」という前向きな理由に変わりました。サイトの構成に合わせて選んでください。