logo
ブログ
2025/11/13

Astroで一部のコンテンツを除いたsitemapの生成 (力技)

はじめに

このサイトでは、本番には生成しないページと、生成はするがインデックスしないページがあります。
@astro/sitemapをつかうと、生成されたページすべてがsitemapに出力されてしまうので、公開したいページだけを含めるようにしました。

Astroでサイトマップを作成する

まずは公式が準備している方法でインストールします。
https://docs.astro.build/ja/guides/integrations-guide/sitemap/

Terminal window
pnpm astro add sitemap
astro.config.mjs
export default defineConfig({
site: "https://example.com/",
// ...
integrations: [
// ...
sitemap(),
],
});

出力をカスタムしたい部分だけ調整する

これでsitemapを出力する環境はできました。
ですがこのままビルドするとインデックスしたくないページも含まれてしまいます。

そこで、まずはカスタマイズしたいパスを丸ごと対象外にします。

一部のパスを対象外にする

私の場合は、/posts/配下にあるパスを独自で生成したいので以下のように設定しました。

astro.config.mjs
export default defineConfig({
// ...
integrations: [
// ...
sitemap({
filter: (page) => !page.startsWith("https://example.com/posts/"),
}),
],
});

独自でsitemapを生成する

これで、/posts/配下のパスはすべてsitemapに出力されなくなりました。

今度は独自でsitemapを生成できるようにします。

pages/sitemap-posts.xml.ts
import { getCollection } from "astro:content";
const SITE = "https://example.com";
export async function GET() {
const posts = (await getCollection("post"))
.filter((p) => (!import.meta.env.PROD || !p.data.isPrivate))
.filter((p) => (!import.meta.env.PROD || !p.data.isDraft));
const urls = posts
.map((p) => {
return `<url><loc>${SITE}/posts/${p.data.slug}/</loc></url>`;
})
.join("");
return new Response(
`<?xml version="1.0" encoding="UTF-8"?><urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"><url><loc>${SITE}/posts/</loc></url>${urls}</urlset>`,
{
headers: {
"Content-Type": "application/xml",
},
},
);
}

力技ですがビルド時に生成されるようにできました。

サイトマップをまとめて配信できるように設定する

さいごに、独自に生成したsitemapをsitemap-index.xmlへ追加します。

astro.config.mjs
export default defineConfig({
// ...
integrations: [
// ...
sitemap({
filter: (page) => !page.startsWith("https://example.com/posts/"),
customSitemaps: ["https://example.com/sitemap-posts.xml"],
}),
],
});

これで新規のページは自動で追加され、独自にフィルターをかけたい箇所も調整されるようになりました。

今回は力技で対応してしまいましたが、簡単にxmlを生成できるツールがあればそれに置き換えたいと思います。