TITLE

Next.jsでサイトマップを生成する ― 静的・動的・大規模分割

投稿日:2026.06.15

CATEGORY

  • Web開発
Next.jsでサイトマップを生成する ― 静的・動的・大規模分割

サードパーティパッケージが不要になった

Pages Router時代、Next.jsでサイトマップを生成するにはnext-sitemapのようなサードパーティパッケージを使うのが一般的でした。App Routerにはサイトマップ生成のファイル規約が組み込まれており、外部パッケージなしで対応できます。

この記事では、App Routerのサイトマップ生成機能を規模ごとに整理します。内容はNext.js公式ドキュメントに基づいています。

3つのアプローチを規模で選ぶ

Next.jsのサイトマップ実装には主に3つのアプローチがあります。

アプローチ向いているケース
静的ファイル直置き小規模・変更頻度が低い
動的生成(sitemap.ts)中規模・DBやCMSと連携
分割生成(generateSitemaps)大規模・50,000URL超

1. 静的ファイルの直置き

最もシンプルな方法は、app/sitemap.xmlにXMLファイルをそのまま置くことです。

<!-- app/sitemap.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>https://example.com</loc>
    <lastmod>2024-01-01</lastmod>
  </url>
  <url>
    <loc>https://example.com/about</loc>
  </url>
</urlset>

このファイルは/sitemap.xmlとして配信されます。数ページ程度の静的サイトや、サイトマップをビルド時に別ツールで生成している場合に適しています。

2. 動的生成(sitemap.ts)

Next.js 13.3.0以降、app/sitemap.tsにdefault export関数を書くことで動的にサイトマップを生成できます。この関数はMetadataRoute.Sitemap型の配列を返します。

import type { MetadataRoute } from 'next'

export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
  // DBやAPIからURLの一覧を取得
  const posts = await fetchAllPosts()

  const postUrls = posts.map((post) => ({
    url: `https://example.com/blog/${post.slug}`,
    lastModified: post.updatedAt,
  }))

  return [
    {
      url: 'https://example.com',
      lastModified: new Date(),
      changeFrequency: 'monthly',
      priority: 1,
    },
    ...postUrls,
  ]
}

型の各フィールドは次のとおりです。

{
  url: string                    // 必須
  lastModified?: Date | string   // 省略可
  changeFrequency?:              // 省略可
    | 'always' | 'hourly' | 'daily'
    | 'weekly' | 'monthly' | 'yearly' | 'never'
  priority?: number              // 省略可 (0.0 〜 1.0)
  alternates?: {                 // hreflang対応 (Next.js 14.2.0+)
    languages?: Record<string, string>
  }
  images?: string[]              // 省略可
  videos?: ...[]                 // 省略可
}

changeFrequencypriorityについて: これらのフィールドはサイトマップの仕様にある項目ですが、Googleはこれらの値を基本的に無視します。順位への影響はありません。クロール頻度の調整に使えると期待されることがありますが、公式に効果が保証されているわけではありません。設定しても問題はありませんが、実装コストをかける優先度は低いと考えてよいです。

sitemap.tsはRoute Handler扱いで、既定ではキャッシュされます。動的なデータを毎回取得したい場合はキャッシュ設定を明示的に変更します。

3. 大規模分割(generateSitemaps)

Googleのサイトマップ仕様では、1ファイルあたりの上限は50,000 URLです。それを超える場合はgenerateSitemaps()を使って分割します。

import type { MetadataRoute } from 'next'

export async function generateSitemaps() {
  // 分割数を決める。例: 総URLを50,000で割った数
  return [
    { id: 0 },
    { id: 1 },
    { id: 2 },
  ]
}

export default async function sitemap({
  id,
}: {
  id: number
}): Promise<MetadataRoute.Sitemap> {
  // id に対応するURLの範囲を取得
  const posts = await fetchPostsBatch(id)

  return posts.map((post) => ({
    url: `https://example.com/blog/${post.slug}`,
    lastModified: post.updatedAt,
  }))
}

この設定で/sitemap/0.xml/sitemap/1.xmlのように複数のサイトマップファイルが生成されます。

Next.js 16.0.0以降の変更: idパラメータの型がPromise<string>になりました。16.0.0以降ではawaitが必要です。使用しているバージョンを確認してください。

// Next.js 16.0.0以降
export default async function sitemap({
  id,
}: {
  id: Promise<string>
}): Promise<MetadataRoute.Sitemap> {
  const resolvedId = await id
  // ...
}

robots.tsとの連携

サイトマップのURLをrobots.txtに記載することで、クローラーがサイトマップを発見しやすくなります。app/robots.tssitemapフィールドに記載すると自動で出力されます。

import type { MetadataRoute } from 'next'

export default function robots(): MetadataRoute.Robots {
  return {
    rules: {
      userAgent: '*',
      allow: '/',
    },
    sitemap: 'https://example.com/sitemap.xml',
  }
}

分割サイトマップを使っている場合は、サイトマップインデックスファイルのURLを指定するか、複数のサイトマップURLを配列で指定します。

Pages Routerでの対応

App Routerのファイル規約(app/sitemap.tsapp/robots.ts)はApp Router専用です。Pages Routerを使っているプロジェクトでは使えません。Pages RouterではAPI Routeを使った実装か、next-sitemapのようなパッケージが必要です。

ここまでをまとめると

Next.js App Routerのサイトマップ機能は、規模に応じて3つの方法から選びます。

  • 静的直置き: app/sitemap.xmlを配置するだけ。小規模向け
  • 動的生成: app/sitemap.tsでDBやAPIと連携。中規模向け
  • 分割生成: generateSitemaps()で50,000URL超に対応。大規模向け

changeFrequencypriorityはGoogleが基本的に無視するため、実装の優先度は低いです。next-sitemapはApp Routerでは不要で、組み込みの機能で同等以上のことができます。

robots.tsでサイトマップのURLを記載することで、クローラーへの案内を一箇所にまとめられます。

出典

AI

AI導入やシステム開発の ご相談を承っています。

お気軽にお問い合わせください