Next.jsでサイトマップインデックスを生成する
#Next_js #SEO
Next.js 13.2でFile-Based Metadata APIが追加され、サイトマップを簡単に生成できるようになった。
https://nextjs.org/docs/app/api-reference/file-conventions/metadata/sitemap
サイトマップの動的生成
// app/sitemap.ts
import { MetadataRoute } from 'next'export default function sitemap(): MetadataRoute.Sitemap {
return [
{
url: process.env.BASE_URL,
lastModified: new Date(),
changeFrequency: 'yearly',
priority: 1,
},
{
url: `${process.env.BASE_URL}/about`,
lastModified: new Date(),
changeFrequency: 'monthly',
priority: 0.8,
},
]
}
サイトマップの分割
多くのURLを含む必要がある場合は、generateSitemaps関数を利用して複数ページに分割することもできる。
// app/post/sitemap.ts
import { getPosts, countPosts } from '@/lib/post';
// Googleは1つのSitemapに50,000URLまで
const PER_PAGE = 50000;
export async function generateSitemaps() {
const count = await countPosts();
const pages = Math.ceil(count / 50000);
// return [{ id: 0 }, { id: 1 }, { id: 2 }, ...];return [...Array(pages)].map((_, i) => ({ id: i });
}
export default async function sitemap({ id }: { id: number }): Promise<MetadataRoute.Sitemap> {
const posts = await getPosts({
page: id,
perPage: PER_PAGE,
});
return posts.map((post) => {
return {
url: `${process.env.BASE_URL}/post/${post.id}`,
lastModified: post.updatedAt,
};
};
}
このサイトマップは、以下のルートに生成される。
NODE_ENV=development
/post/sitemap/[id].xml
NODE_ENV=production
/post/sitemap.xml/[id]
サイトマップインデックスの動的生成
複数のサイトマップを検索エンジンに送信する場合はサイトマップインデックスを利用するのが便利だが、現在Next.jsは対応していないらしい。
https://github.com/vercel/next.js/discussions/61025
そのため、ルートハンドラ(Route Handlers)で無理やり実装する。
// app/sitemap-index/post/sitemap.xml/route.ts
export const dynamic = 'force-dynamic';
import { countPosts } from '@/lib/post';
// Googleは1つのSitemapに50,000URLまでconst PER_PAGE = 50000;
export async function GET() {
const count = await countPosts();
const pages = Math.ceil(count / PER_PAGE);
const sitemaps = [...Array(pages)].map((_, i) => {
if (process.env.NODE_ENV === "development") {
return `<sitemap><loc>${process.env.BASE_URL}/sitemap/post/sitemap.xml/${i}</loc></sitemap>`;
} else {
return `<sitemap><loc>${process.env.BASE_URL}/sitemap/post/sitemap/${i}.xml</loc></sitemap>`;
}
});
const xml = `<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
${sitemaps.join("")}
</sitemapindex>
`;
return new Response(xml, {
headers: {
"Content-Type": "application/xml",
},
});
}
以下のルートにサイトマップインデックスが生成される。
/sitemap-index/post/sitemap.xml