【Astro】サイトマップ(sitemap.xml)をインテグレーションなしで自作する

Astroには公式インテグレーションの@astrojs/sitemapがあるおかげで、npx astro add sitemapを叩くだけでpages配下の各ルートを全て含んだxmlファイルを自動で作成してくれるため、非常に簡単にサイトマップを配置できる。

しかしその反面、当サイトのようなブログサイトでありがちな下記要件を満たすのは少し手間がかかる。

  • 記事の更新日をlastmodに指定したい
  • noindexにしている記事(パス)を除外したい
  • sitemap.xmlというファイル名で作成したい(上記インテグレーションだとsitemap-index.xmlsitemap-0.xmlの2ファイルが作成されてしまう)

インテグレーションをカスタムするという方法もあるが、今後改修する際の融通も効きやすさを考慮して今回はサイトマップを自前で実装してみる。

実装方法

0. サンプル記事の用意

type Article = {
path: string;
updatedAt: Date;
index: boolean;
};
export const EXAMPLE_ARTICLES: Article[] = [
{
path: "/article-001",
updatedAt: new Date(),
index: true,
},
{
path: "/article-002",
updatedAt: new Date(),
index: true,
},
{
path: "/article-003",
updatedAt: new Date(),
index: false,
},
];

今回は例として上記のようなArticleオブジェクト群を用いる。

3つ目の記事だけnoindexにしたいという前提で、それぞれのupdatedAtは適当に指定している。

1. xmlの構築

type SitemapItem = {
loc: string;
lastmod: Date;
};
export function generateSitemap(items: SitemapItem[]) {
const itemsStr = items
.map(
({ loc, lastmod }) =>
`<url><loc>${loc}</loc><lastmod>${lastmod.toJSON()}</lastmod></url>`,
)
.join("");
return `<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="https://www.sitemaps.org/schemas/sitemap/0.9">
${itemsStr}
</urlset>
`;
}

サイトマップの中身を生成する関数を作成する。

2. APIルートの定義

import { generateSitemap } from "../utils/generateSitemap";
import { EXAMPLE_ARTICLES } from "../utils/consts";
export async function GET() {
const sitemapItems = EXAMPLE_ARTICLES.filter((article) => article.index).map(
(article) => {
return {
loc: "https://example.com" + article.path,
lastmod: article.updatedAt,
};
},
);
const sitemap = generateSitemap(sitemapItems);
const res = new Response(sitemap);
res.headers.set("Content-Type", "text/xml");
return res;
}

/sitemap.xmlというエンドポイントでレスポンスを返すために、src/pages/sitemap.xml.tsを作成しAPIルートを定義する。

<urlset xmlns="https://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://example.com/article-001</loc>
<lastmod>2023-09-15T12:25:26.998Z</lastmod>
</url>
<url>
<loc>https://example.com/article-002</loc>
<lastmod>2023-09-15T12:25:26.998Z</lastmod>
</url>
</urlset>

試しにhttp://localhost:4321/sitemap.xmlを叩いてみると、無事期待通りのxmlが返ってきた。noindexにしたい記事もしっかり除外されている。

3. サイトマップの登録

<head>
<link rel="sitemap" href="/sitemap.xml" />
</head>
Sitemap: <ORIGIN>/sitemap.xml

あとはクローラー向けに、<head>内とrobots.txtにサイトマップの設定を追記すれば完了。