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-sitemapnext-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 の場所を明記
}
}よくある間違い集
- Sitemap の場所を書いていない: robots.txt の最後に
Sitemap: https://.../sitemap.xmlと書いておかないと、クローラーは Sitemap を見つけられません。 - ワイルドカードの誤用:
Disallow: /*?のように書いて、パラメータ付きの重要なページまでブロックしてしまう。 - 大文字小文字: robots.txt は大文字小文字を区別します(ディレクトリ名など)。
最後の仕上げ:Google Search Console への登録
ファイルを用意しただけでは不十分です。Google に「用意したから見てね」と伝える必要があります。
- Google Search Console にアクセスし、サイトを登録します(未登録の場合)。
- 左メニューの「サイトマップ (Sitemaps)」をクリック。
- 「新しいサイトマップの追加」欄に
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 はその土台となるインフラストラクチャーです。
app/sitemap.tsで動的な Sitemap を自動生成する。app/robots.tsで環境に応じたクロール制御を行う。- Middleware でこれらのファイルをブロックしないように注意する。
- Google Search Console に送信して状態を監視する。
この4ステップで、あなたのサイトは検索エンジンに対して「ウェルカム状態」になります。あとは素晴らしいコンテンツを作るだけです!
Next.js SEO基盤構築フロー
Sitemap と robots.txt の作成から Search Console への登録手順
⏱️ Estimated time: 20 min
- 1
Step1: sitemap.ts の作成
`app/sitemap.ts` を作成し、サイト内の固定ページと動的ページ(ブログ記事など)の URL リストを返す関数をエクスポートします。 - 2
Step2: robots.ts の作成
`app/robots.ts` を作成し、本番環境では許可、開発環境ではブロックするなど、環境に応じたルールを記述します。必ず Sitemap の URL を含めてください。 - 3
Step3: Middleware の確認
認証などの Middleware を使用している場合、`sitemap.xml` と `robots.txt` がブロックされないように `matcher` の除外設定を確認します。 - 4
Step4: Search Console への送信
Google Search Console のサイトマップメニューから `sitemap.xml` を送信し、ステータスが「成功」になることを確認します。
FAQ
sitemap.xml にはどれくらいの URL を含められますか?
lastModified や changeFrequency は設定したほうがいいですか?
新しい記事を公開したら、すぐに Sitemap を再送信する必要がありますか?
Next.js の動的ルート(Dynamic Routes)はどう扱えばいいですか?
4 min read · 公開日: 2025年12月20日 · 更新日: 2026年1月22日
関連記事
Next.js ファイルアップロード完全ガイド:S3/Qiniu Cloud 署名付き URL 直接アップロード実践

Next.js ファイルアップロード完全ガイド:S3/Qiniu Cloud 署名付き URL 直接アップロード実践
Next.js Eコマース実践:カートと Stripe 決済の完全実装ガイド

Next.js Eコマース実践:カートと Stripe 決済の完全実装ガイド
Next.js ユニットテスト実践:Jest + React Testing Library 完全設定ガイド


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