言語を切り替える
テーマを切り替える

Next.js Sitemap と robots.txt 設定ガイド:検索エンジンに「見つけてもらう」ための最短ルート

苦労して開発した Web サイトをようやく公開し、意気揚々と Google で検索してみる。「……ん? 出てこない」。
数日待っても、キーワードを変えても、結果は同じ。Google Search Console を開くと、送信したはずの Sitemap が「取得できませんでした」という冷たいエラーメッセージを表示している。

この絶望感、私も経験があります。初めて Next.js プロジェクトを立ち上げた時、Sitemap の配置場所を間違えていたり、robots.txt で誤ってサイト全体をブロック (Disallow: /) していたりと、初歩的なミスで一ヶ月ボウに振ったことがあります。

検索エンジンにインデックスされなければ、そのサイトはインターネットの孤島です。どんなに素晴らしいコンテンツがあっても、誰もたどり着けません。

この記事では、私が過去の失敗から学んだ、Next.js (App Router) における Sitemap と robots.txt の「正しい」設定方法を共有します。静的サイトから大規模な動的サイトまで、3つのパターンに応じた最適な実装方法と、絶対にやってはいけない設定ミスを解説します。

なぜ Sitemap と robots.txt が必要なのか?

Sitemap:検索エンジンのための地図

Sitemap (sitemap.xml) は、Google などの検索エンジンに対して「私のサイトにはこんなページがありますよ」と教えるファイルです。

クローラーは通常、リンクを辿ってページを発見しますが、新しく作られたばかりのページや、どこからもリンクされていない深い階層のページは見つけにくいものです。Sitemap を提出することで、これらのページを積極的にクローラーに通知し、インデックス(検索結果への登録)を早めることができます。

robots.txt:クローラーへの指示書

robots.txt は、どのページをクロールしてよくて、どのページはダメかを指示するテキストファイルです。
管理画面 (/admin) や API エンドポイント (/api) など、検索結果に出したくないページをブロックするために使います。

最大の注意点:robots.txt の設定を間違えると、サイト全体が検索結果から消滅します。本当です。

Next.js で Sitemap を生成する3つの方法

Next.js 13 以降の App Router では、ファイルベースのメタデータ API が導入され、Sitemap の作り方も簡単になりました。

方法1: App Router 標準 sitemap.ts(おすすめ)

適用シーン: 中小規模のサイト、動的なブログなど

app/sitemap.ts というファイルを作るだけで、Next.js が自動的に XML を生成してくれます。TypeScript で書けるので、型安全性も抜群です。

// app/sitemap.ts
import { MetadataRoute } from 'next'

export default function sitemap(): MetadataRoute.Sitemap {
  return [
    {
      url: 'https://yourdomain.com',
      lastModified: new Date(),
      changeFrequency: 'yearly',
      priority: 1,
    },
    {
      url: 'https://yourdomain.com/about',
      lastModified: new Date(),
      changeFrequency: 'monthly',
      priority: 0.8,
    },
    {
      url: 'https://yourdomain.com/blog',
      lastModified: new Date(),
      changeFrequency: 'weekly',
      priority: 0.5,
    },
  ]
}

これで https://yourdomain.com/sitemap.xml にアクセスすると、正しい XML が表示されます。

方法2: 動的コンテンツを含める

ブログ記事のように増減するページを含める場合も、sitemap.ts で非同期処理を書くだけです。

// app/sitemap.ts
import { MetadataRoute } from 'next'
import { getAllPosts } from '@/lib/posts' // 記事取得関数

export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
  // 1. 固定ページ
  const staticPages: MetadataRoute.Sitemap = [
    {
      url: 'https://yourdomain.com',
      lastModified: new Date(),
      changeFrequency: 'yearly',
      priority: 1,
    },
    // ...その他
  ]

  // 2. 動的ページ(ブログ記事など)
  const posts = await getAllPosts()
  const postPages: MetadataRoute.Sitemap = posts.map((post) => ({
    url: `https://yourdomain.com/blog/${post.slug}`,
    lastModified: new Date(post.updatedAt),
    changeFrequency: 'weekly',
    priority: 0.7,
  }))

  return [...staticPages, ...postPages]
}

これで、新しい記事を公開するたびに Sitemap も自動的に更新されます。

方法3: next-sitemap パッケージを使う

適用シーン: 大規模サイト(5万URL以上)、 Pages Router を使用している場合

超大規模サイトで Sitemap ファイルを分割したい場合や、設定ファイルで一括管理したい場合は、next-sitemap という外部ライブラリが便利です。

npm install next-sitemap

next-sitemap.config.js を作成:

/** @type {import('next-sitemap').IConfig} */
module.exports = {
  siteUrl: process.env.SITE_URL || 'https://yourdomain.com',
  generateRobotsTxt: true, // robots.txt も一緒に作る
  // ...詳細設定
}

package.json のビルドスクリプトに追加:

"scripts": {
  "postbuild": "next-sitemap"
}

robots.txt の正しい書き方

App Router では app/robots.ts で動的に生成できます。これが非常に強力なのは、環境ごとに設定を変えられる点です。

開発環境と本番環境で出し分ける

「開発中のテストサイトが Google にインデックスされてしまった!」という事故を防ぐため、以下のように分岐処理を入れましょう。

// app/robots.ts
import { MetadataRoute } from 'next'

export default function robots(): MetadataRoute.Robots {
  const baseUrl = 'https://yourdomain.com'
  
  // 開発環境やプレビュー環境では全ブロック
  if (process.env.VERCEL_ENV !== 'production') {
    return {
      rules: {
        userAgent: '*',
        disallow: '/',
      },
    }
  }

  // 本番環境の設定
  return {
    rules: [
      {
        userAgent: '*',
        allow: '/', // 基本的に許可
        disallow: [ // 見せたくない場所だけブロック
          '/_next/',
          '/api/',
          '/admin/',
          '/private/',
        ],
      },
      // GPTBot などの AI 学習用クローラーをブロックしたい場合
      {
        userAgent: 'GPTBot',
        disallow: ['/'],
      }
    ],
    sitemap: `${baseUrl}/sitemap.xml`, // Sitemap の場所を明記
  }
}

よくある間違い集

  1. Sitemap の場所を書いていない: robots.txt の最後に Sitemap: https://.../sitemap.xml と書いておかないと、クローラーは Sitemap を見つけられません。
  2. ワイルドカードの誤用: Disallow: /*? のように書いて、パラメータ付きの重要なページまでブロックしてしまう。
  3. 大文字小文字: robots.txt は大文字小文字を区別します(ディレクトリ名など)。

最後の仕上げ:Google Search Console への登録

ファイルを用意しただけでは不十分です。Google に「用意したから見てね」と伝える必要があります。

  1. Google Search Console にアクセスし、サイトを登録します(未登録の場合)。
  2. 左メニューの「サイトマップ (Sitemaps)」をクリック。
  3. 「新しいサイトマップの追加」欄に sitemap.xml と入力して「送信」。

「成功」ステータスになればOKです。もし「取得できませんでした」となる場合は、以下の原因を探ってください。

トラブルシューティング

Q: 「取得できませんでした」と出る
A: Next.js の Middleware で Googlebot をブロックしていないか確認してください。認証ロジック (auth-middleware など) が sitemap.xml へのアクセスを遮断していませんか?

// middleware.ts の matcher で除外設定をする例
export const config = {
  matcher: [
    // ...
    '/((?!api|_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)',
  ],
}

Q: 送信したのにインデックスされない
A: Google は「品質の低いページ」や「重複コンテンツ」をインデックスしない傾向があります。ページの内容が薄くないか、noindex タグが入っていないか(<meta name="robots" content="noindex" />)を確認してください。

まとめ

SEO 対策というとキーワード選びなどに目が行きがちですが、Sitemap と robots.txt はその土台となるインフラストラクチャーです。

  1. app/sitemap.ts で動的な Sitemap を自動生成する。
  2. app/robots.ts で環境に応じたクロール制御を行う。
  3. Middleware でこれらのファイルをブロックしないように注意する。
  4. Google Search Console に送信して状態を監視する。

この4ステップで、あなたのサイトは検索エンジンに対して「ウェルカム状態」になります。あとは素晴らしいコンテンツを作るだけです!

Next.js SEO基盤構築フロー

Sitemap と robots.txt の作成から Search Console への登録手順

⏱️ Estimated time: 20 min

  1. 1

    Step1: sitemap.ts の作成

    `app/sitemap.ts` を作成し、サイト内の固定ページと動的ページ(ブログ記事など)の URL リストを返す関数をエクスポートします。
  2. 2

    Step2: robots.ts の作成

    `app/robots.ts` を作成し、本番環境では許可、開発環境ではブロックするなど、環境に応じたルールを記述します。必ず Sitemap の URL を含めてください。
  3. 3

    Step3: Middleware の確認

    認証などの Middleware を使用している場合、`sitemap.xml` と `robots.txt` がブロックされないように `matcher` の除外設定を確認します。
  4. 4

    Step4: Search Console への送信

    Google Search Console のサイトマップメニューから `sitemap.xml` を送信し、ステータスが「成功」になることを確認します。

FAQ

sitemap.xml にはどれくらいの URL を含められますか?
プロトコル仕様では 50,000 URL、サイズは 50MB までです。これを超える場合は、`sitemap-1.xml`, `sitemap-2.xml` のようにファイルを分割し、それらをまとめる `sitemap-index.xml` を作る必要があります(`next-sitemap` などのツールを使うと自動でやってくれます)。
lastModified や changeFrequency は設定したほうがいいですか?
Google は `lastModified`(最終更新日)を重要視しますが、`changeFrequency`(更新頻度)や `priority`(優先度)は現在はあまり考慮していないと言われています。`lastModified` だけは正確な日付を入れるようにしましょう。
新しい記事を公開したら、すぐに Sitemap を再送信する必要がありますか?
Google は定期的に Sitemap を見に来るので、手動で毎回再送信する必要はありません。ただし、急ぎでインデックスさせたい重要なニュース記事などの場合は、Search Console の「URL 検査」ツールから個別にインデックス登録リクエストを送るのが早道です。
Next.js の動的ルート(Dynamic Routes)はどう扱えばいいですか?
`app/sitemap.ts` 内でデータベースや CMS からデータ一覧(スラッグなど)を fetch し、map 関数を使って URL オブジェクトの配列を生成して返せば、自動的に Sitemap に反映されます。

4 min read · 公開日: 2025年12月20日 · 更新日: 2026年1月22日

コメント

GitHubアカウントでログインしてコメントできます

関連記事