
Astroでブログを公開したけど、サイトマップってどうやって用意すればいいの?

XMLを手で書くのは大変そう…。記事を増やすたびに書き直すのかな?
Astroでサイトを公開したあと、「サイトマップも用意したほうがいいのかな」と気になっていませんか?
WordPressならプラグインで済んでいた部分なので、静的サイトではどうするのか迷いやすいところだと思います。
結論からいうと、Astroなら公式インテグレーションの @astrojs/sitemap を入れるのが手軽です。
ビルドのたびにページの一覧からサイトマップを作ってくれるので、記事を足すたびに手で書き直す必要はありません。
ただし、site の設定を忘れてもエラーにならなかったり、開発サーバーでは生成されなかったりと、気づきにくいポイントもあります。
この記事では、導入から検索エンジンへの伝え方、よく使うオプション、生成されないときの確認までを順番に整理していきます。
- サイトマップの役割と、@astrojs/sitemap の導入手順
- robots.txt・head・Google Search Console でサイトマップの場所を伝える方法
filter・serializeでのページ除外と、changefreq・lastmod の扱い方- サイトマップが生成されない・反映されないときの確認ポイント
このブログもAstroと@astrojs/sitemapの組み合わせで動いています。WordPressから移ってきた経緯は別記事にまとめているので、よければあわせてどうぞ。

- Astro 7.3系と @astrojs/sitemap 3.7.4(2026年8月31日リリース)を対象にした内容です
- パッケージマネージャは pnpm で書いていますが、npm・yarn でもコマンドを読み替えれば同じです
公式ドキュメントは @astrojs/sitemap(Astro Docs) にあります。
サイトマップとは?検索エンジンに渡すページURLの一覧
サイトマップは、サイト内にどんなページがあるかを検索エンジンに伝えるためのファイルです。
中身は、ページのURLを並べたXML形式のリストになっています。
検索エンジンは、ページ内のリンクをたどって新しいページを見つけていくのが基本です。
サイトマップはそれとは別に、「このサイトにはこういうURLがあります」とまとめて渡しておくためのもの、というイメージです。
建物でいえば、入口に置いてある館内案内図のようなものです。
案内図がなくても歩き回れば部屋は見つかりますが、あれば全体を把握しやすくなります。
URLの一覧を決まった書式のXMLで書いたファイルのことです。
1つのURLごとに <url> の中へ <loc>(ページのURL)を入れ、必要に応じて <lastmod>(最終更新日)などを添える形になっています。
注意したいのは、サイトマップはあくまでURLを知らせる手段の1つだということです。
サイトマップに載せたからといって、そのページが検索結果に出ることが約束されるわけではありません。
@astrojs/sitemap でサイトマップを生成する手順
Astroには公式インテグレーションの @astrojs/sitemap があり、ビルドのときにページの一覧からサイトマップを書き出してくれます。
やることは、インテグレーションの追加・site の設定・ビルドでの確認の3つです。
1. インテグレーションを追加する
いちばん手軽なのは、astro add コマンドを使う方法です。
pnpm astro add sitemap
パッケージのインストールと astro.config.mjs への追記をまとめてやってくれます。npm なら npx astro add sitemap です。
手動で入れる場合は、パッケージを追加してから設定ファイルに書き足します。
pnpm add @astrojs/sitemap
設定ファイルでは、sitemap を読み込んで integrations に入れます。
// astro.config.mjs
import { defineConfig } from "astro/config";
import sitemap from "@astrojs/sitemap";
export default defineConfig({
site: "https://example.com",
integrations: [sitemap()],
});
integrations の配列に sitemap() を入れるだけで、オプションを何も渡さなくても動きます。
2. site にサイトの公開URLを設定する
上のコードで一緒に書いている site が、このインテグレーションでいちばん大事な設定です。
@astrojs/sitemap は、この値を使ってページの完全なURLを組み立てます。
やっかいなのは、site を書き忘れてもビルドはエラーにならないことです。
代わりに、ビルドのログにこんな警告が出て、サイトマップの生成だけがスキップされます。
The Sitemap integration requires the `site` astro.config option. Skipping.
ビルド自体は成功して見えるので、サイトマップだけ出ていないことに気づきにくいんですよね。
導入したら、ログにこの警告が出ていないか一度見ておくと安心です。
らるじゅエラーで止まってくれれば一発で気づけるんですが、警告だけで先に進むのがちょっと意地悪なところ。
「sitemapを入れたらsiteも書く」とセットで覚えておくのがいいと思います。
3. ビルドして sitemap-index.xml ができているか確認する
@astrojs/sitemap はビルドが終わったタイミングでサイトマップを書き出します。
つまり astro dev の開発サーバーでは生成されないので、確認はビルドしてから行います。
pnpm build
ビルドが終わると、出力先の dist/ に次の2種類のファイルができます。
| ファイル | 役割 |
|---|---|
sitemap-index.xml | 子サイトマップの場所をまとめた目次。検索エンジンにはこちらを伝える |
sitemap-0.xml | 実際のページURLが並んでいる本体 |
sitemap-index.xml はページのURLを直接持つのではなく、sitemap-0.xml のような子サイトマップを束ねる役割です。
URLの数が上限(既定は1ファイル45,000件)を超えると sitemap-1.xml 以降に分かれ、それも index にまとめて載ります。
見やすく改行すると、sitemap-index.xml の中身はおおよそ次のような形です(example.com の例)。
<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<sitemap>
<loc>https://example.com/sitemap-0.xml</loc>
</sitemap>
</sitemapindex>
sitemap-0.xml のほうには、ページごとに <url> と <loc> が並びます。
オプションを指定しない既定の状態では <lastmod> などは付かず、URLだけのシンプルな一覧になります。
このブログも同じ構成で、sitemap-index.xml から sitemap-0.xml を1つだけ参照する形になっています。
サイトマップの場所を検索エンジンに伝える
サイトマップができたら、次はどこにあるのかを知らせておく準備です。
方法は主に3つあり、このブログではそのうち robots.txt と head の2か所に書いています。
robots.txt にサイトマップのURLを書く
robots.txt は、クローラー向けのルールを書いておくファイルです。
ここに Sitemap: の行を足しておくと、サイトマップの場所も一緒に伝えられます。
静的なファイルで置くなら、public/robots.txt を作ってこう書きます。
User-agent: *
Allow: /
Sitemap: https://example.com/sitemap-index.xml
ドメインを直書きしたくない場合は、src/pages/robots.txt.ts というエンドポイントを作り、site の値から組み立てる方法もあります。
// src/pages/robots.txt.ts
import type { APIRoute } from "astro";
const getRobotsTxt = (sitemapURL: URL) => `User-agent: *
Allow: /
Sitemap: ${sitemapURL.href}`;
export const GET: APIRoute = ({ site }) => {
const sitemapURL = new URL("sitemap-index.xml", site);
return new Response(getRobotsTxt(sitemapURL));
};
こちらは astro.config.mjs の site を読んで Sitemap: の行を作るので、ドメインを変えたときの書き換え漏れを防げます。
静的ファイルとエンドポイントは、どちらか片方を用意すれば十分です。
head に <link rel="sitemap"> を入れる
もう1つは、ページの <head> にサイトマップへのリンクを入れる方法です。公式ドキュメントでも、この1行を入れておくことが推奨されています。
レイアウトの head に、次のように追加します。
<head>
<!-- ほかの meta タグなどと並べて置く -->
<link rel="sitemap" href="/sitemap-index.xml" />
</head>
共通の head をまとめたコンポーネントがあるなら、そこに1行足しておけば全ページに入ります。
このブログでも、head 用のコンポーネントにこの1行を入れています。
Google Search Console にサイトマップを送信する
Googleに対しては、Google Search Console から直接サイトマップを送信することもできます。
- Search Console で対象のサイトを開く
- 左メニューの「サイトマップ」を開く
sitemap-index.xmlのURLを入力して送信する
送るのは sitemap-index.xml の1つだけで大丈夫です。
index には子サイトマップの場所が書かれているので、そこから sitemap-0.xml などもたどってもらえます。
なお、送信はあくまで「サイトマップの場所を知らせる」操作です。
送ったページがすべて検索結果に載る、という仕組みではない点は押さえておきましょう。
よく使う設定オプション|filter・serialize・lastmod
@astrojs/sitemap は、sitemap() にオプションを渡して挙動を変えられます。
ここでは出番の多そうな3つを取り上げて、最後に一覧表でまとめます。
filter でサイトマップに載せたくないページを外す
特定のページをサイトマップから外したいときは filter を使います。
関数には各ページの完全なURLの文字列が渡ってくるので、残したいページなら true、外したいページなら false を返します。
たとえば、一覧の2ページ目以降のように、URLの末尾が /2/ /3/ と数字だけになっているページを外すなら、こう書けます。
// astro.config.mjs
import { defineConfig } from "astro/config";
import sitemap from "@astrojs/sitemap";
export default defineConfig({
site: "https://example.com",
integrations: [
sitemap({
// パスの末尾が「/数字/」のページを除外する
filter: (page) => !/\/\d+\/$/.test(new URL(page).pathname),
}),
],
});
page は https://example.com/2/ のような完全なURLなので、new URL(page).pathname でパスの部分だけを取り出して判定しています。
末尾にスラッシュが付くURL構成を前提にした書き方で、スラッグが数字だけの記事ページも一緒に外れる点には注意してください。
ちなみに、このブログのサイトマップにもトップの一覧の /2/ /3/ や、カテゴリのページが含まれています。
こうしたページを外すかどうかはサイトの方針次第で、外さないといけないものではありません。
changefreq・priority・lastmod は入れるべき?
@astrojs/sitemap には、changefreq(更新頻度)・priority(優先度)・lastmod(最終更新日)を付けるオプションもあります。
ただ、Google向けに限っていえば、無理に入れなくてよいと思います。
Googleは、サイトマップの作り方を説明した公式ドキュメントで、priority と changefreq の値は無視すると明言しています。
lastmod のほうは、Googleが使う場合があります。
ただし条件つきで、一貫して正確で、確認できる場合に使うとされています。
日付も、ページの主要な内容や構造化データ、リンクが変わったときのものであるべきで、著作権表記を直しただけのような更新は含みません。
ここで気をつけたいのが、@astrojs/sitemap の lastmod オプションの仕様です。
このオプションは日付(Date)を1つ受け取るだけなので、すべてのURLに同じ日付が付きます。
つまり、ビルドした日付を一律に入れると、実際には更新していない記事まで「ビルド日に更新された」ことになってしまいます。
Googleが正確な lastmod を前提にしている以上、意味が薄いうえに、逆効果にもなりえます。
ページごとの本当の更新日を出したい場合は、serialize を使って、URLと記事の更新日を自分で対応付ける必要があります。
記事データの持ち方によって書き方が変わるので、ここでは深入りしません。
このブログも lastmod は出しておらず、オプションを何も指定しない既定のままです。
らるじゅ「とりあえず全部入れておこう」となりがちなオプションですが、全URLに同じ日付が並ぶなら出さないほうがすっきりします。
入れるなら、ページごとに正しい日付を出せるようになってから、が良さそうです。
serialize で URL ごとに加工・除外する
filter よりも細かく扱いたいときは serialize を使います。
サイトマップに書き出す直前に1件ずつ呼ばれる関数で、undefined を返すとそのURLを除外、item を書き換えて返すと内容を変えられます。
公式ドキュメントの例に沿うと、こんな形です。
// astro.config.mjs
import { defineConfig } from "astro/config";
import sitemap, { ChangeFreqEnum } from "@astrojs/sitemap";
export default defineConfig({
site: "https://example.com",
integrations: [
sitemap({
serialize(item) {
// URL に「exclude-from-sitemap」を含むページは載せない
if (/exclude-from-sitemap/.test(item.url)) {
return undefined;
}
// 特定のページだけ値を書き換える
if (/your-special-page/.test(item.url)) {
item.changefreq = ChangeFreqEnum.DAILY;
}
return item;
},
}),
],
});
item.url にはページの完全なURLが入っています。
書き換えなかった item も return するのを忘れずに。何も返さないと undefined と同じ扱いになり、除外されてしまいます。
例の changefreq は、前の見出しのとおりGoogleは使わない値なので、あくまで書き方の例として見てください。
オプション一覧
ここまで紹介したものも含めて、@astrojs/sitemap 3.7.4 で指定できる主なオプションをまとめておきます。
| オプション | 既定値 | 内容 |
|---|---|---|
filter | — | ページごとに載せるかを決める関数。引数は完全なURL |
customPages | — | Astroが管理していないページのURLを追加する |
customSitemaps | — | 外部のサイトマップを index に追加する(3.5.0〜) |
entryLimit | 45000 | 1ファイルに入れるURL数の上限。超えると次のファイルに分かれる |
changefreq / priority / lastmod | — | 全URLに同じ値を付ける |
serialize | — | 書き出す直前に1件ずつ加工・除外する関数 |
i18n | — | 多言語サイト向けに、既定の言語と各言語の対応を指定する |
xslURL | — | サイトマップに適用するXSLスタイルシートのURL(3.2.0〜) |
namespaces | すべて有効 | news・xhtml・image・video の名前空間を出すかどうか(3.6.0〜) |
chunks | — | 条件ごとにサイトマップを複数のファイルに分ける(3.7.0〜) |
filenameBase | sitemap | 出力ファイル名の先頭部分(3.4.0〜) |
サイトマップが生成されない・反映されないときの確認ポイント
「導入したはずなのにサイトマップが見当たらない」「載っているはずのページがない」というときは、次の順番で見ていくと原因を絞りやすいです。
astro.config.mjsにsiteを設定しているか(未設定だと警告だけ出てスキップされる)- 開発サーバーではなく、
pnpm buildのあとのdist/を見ているか - 載っていないのが、オンデマンドレンダリング(SSR)する動的ルートのページではないか
filterやserializeで、意図せず外していないか- デプロイ先のビルド成果物に
sitemap-index.xmlが含まれているか
なお、サイトマップの対象になるページが1件もないときも、警告を出すだけでサイトマップは作られません。
見落としやすいのが、3つ目のオンデマンドレンダリングのページです。
@astrojs/sitemap は、SSRで動かしている動的ルートについてはサイトマップのエントリを作れません。
一方で、getStaticPaths() を使ってビルド時にURLが決まるページは、動的ルートでもサイトマップに載ります。
記事ページや一覧ページを getStaticPaths() で静的に生成しているなら、この点は心配いりません。
getStaticPaths() の書き方や、SSRに切り替えたときの違いは別記事で整理しています。

最後のデプロイ先は、ローカルの dist/ にはできているのに、本番のURLで開くと見つからないケースです。
ホスティング側のビルドコマンドや出力ディレクトリの設定が、ローカルと同じになっているかを確認してみてください。
まとめ|サイトマップは作ったあと「場所を伝える」まで
@astrojs/sitemap を使えば、Astroのサイトでもビルドのたびにサイトマップを自動で書き出せます。
押さえる設定は多くなく、site を忘れずに書くことと、できたサイトマップの場所を伝えることの2つが中心です。
changefreq や lastmod などのオプションは、入れればよいというものではありません。
まずは既定のまま動かして、外したいページが出てきたら filter や serialize を足していくのが扱いやすいと思います。
- @astrojs/sitemap は
pnpm astro add sitemapで追加でき、ビルド時にsitemap-index.xmlとsitemap-0.xmlを書き出す siteが未設定だとエラーではなく警告だけでスキップされるので、ログを確認しておく- 開発サーバーでは生成されないので、確認は
pnpm buildのあとのdist/で行う - サイトマップの場所は robots.txt・head の
<link rel="sitemap">・Search Console で伝えられる - Googleは
changefreqとpriorityを使わず、lastmodオプションは全URLに同じ日付が付く点に注意 - 載せたくないページは
filterかserializeで外せる
らるじゅサイトマップは一度入れてしまえば、あとはビルドのたびに勝手に作り直してくれる、手のかからない仕組みです。
まずは site の設定と、ビルド後の dist/ の確認から始めてみてください!
