プッシュ通知
新記事をすぐにお知らせ
🎙️ 音声: ずんだもん / 春日部つむぎ(VOICEVOX)
app/sitemap.tsでビルド時に自動生成、Pages Routerではnext-sitemapパッケージで対応できますNext.jsでsitemap.xmlを静的生成することは、現代のWebアプリケーション開発において必須のSEO対策です。App Routerなら公式対応で手軽に実装でき、Pages Routerでもnext-sitemapで簡単に対応できます。生成したファイルをGoogle Search Consoleに登録し、適切なキャッシュ戦略を組み合わせることで、検索エンジンからの流入を最大化できます。
sitemap.xml(XMLサイトマップ)は、Webサイト全体のURLリストを構造化されたXML形式で検索エンジンボットに提供するファイルです。このファイルの主な目的は、Google、Bing、その他の検索エンジンのクローラーに対して、サイト内のすべてのページが存在することを明確に伝えることにあります。
従来のWebサイトでは、検索エンジンボットが内部リンクをたどることでページを発見していました。しかし、動的に生成されるページや、サイト内のリンク構造が複雑な場合、クローラーが全ページを効率的に発見できないという課題がありました。sitemap.xmlはこの問題を解決し、クローラーが確実にすべてのページを認識できるようにするツールなのです。
sitemap.xmlをGoogle Search Consoleに登録することで、以下のメリットが得られます:
クローリング効率の向上:検索エンジンボットが効率的にサイト内を巡回でき、新しいページや更新されたページを素早く発見できます。これは特に、更新頻度が高いサイトやコンテンツが多いサイトにおいて重要です。
インデックス登録の促進:sitemap.xmlに記載されたURLは、より確実にGoogleのインデックスに登録される傾向があります。インデックスされなければ検索結果に表示されないため、これは検索流入を増やすために必須の施策です。
更新情報の伝達:各URLにlastmod(最終更新日)を記載することで、Googleに対してページが更新されたことを明確に伝えられます。これにより、古いキャッシュを削除し、最新のコンテンツをインデックスする優先度が上がります。
優先度の指定:priorityタグを使用することで、サイト内でどのページが重要かをGoogleに伝えられます。ただし、Googleはこの値を参考程度にしか扱わないため、過度に依存する必要はありません。
Next.js 13で導入されたApp Routerでは、app/sitemap.tsファイルを作成することで、ビルド時に自動的にsitemap.xmlが生成されます。これはNext.jsの公式機能であり、追加のパッケージを必要としない最もシンプルな実装方法です。
基本的な実装例:
// app/sitemap.ts
import { MetadataRoute } from 'next'
export default function sitemap(): MetadataRoute.Sitemap {
const baseURL = 'https://example.com'
// 静的ページのURL定義
const staticPaths: MetadataRoute.Sitemap = [
{
url: `${baseURL}`,
lastModified: new Date(),
changeFrequency: 'yearly',
priority: 1.0,
},
{
url: `${baseURL}/about`,
lastModified: new Date('2025-12-01'),
changeFrequency: 'monthly',
priority: 0.8,
},
{
url: `${baseURL}/privacy`,
lastModified: new Date('2025-11-15'),
changeFrequency: 'yearly',
priority: 0.3,
},
{
url: `${baseURL}/contact`,
lastModified: new Date(),
changeFrequency: 'monthly',
priority: 0.7,
},
]
return staticPaths
}
このシンプルな例では、静的ページのURLのみをsitemap.xmlに含めています。各URLに対して、最終更新日(lastModified)、更新頻度(changeFrequency)、優先度(priority)を指定しています。
App Routerの真の力は、ビルド時に動的なデータを取得し、静的なURLと組み合わせることができる点にあります。ブログ記事、商品情報、ユーザープロフィールなど、データベースやCMSから取得したコンテンツのURLを自動的にsitemap.xmlに含めることができます。
動的URLを含む実装例:
// app/sitemap.ts
import { MetadataRoute } from 'next'
// ブログ記事データを取得する関数(例:データベースやAPI)
async function getArticles() {
try {
const response = await fetch('https://api.example.com/articles', {
// ISR対応:次のビルドまでキャッシュ
next: { revalidate: 86400 } // 24時間ごとに再検証
})
return await response.json()
} catch (error) {
console.error('Failed to fetch articles:', error)
return []
}
}
// 商品データを取得する関数
async function getProducts() {
try {
const response = await fetch('https://api.example.com/products', {
next: { revalidate: 43200 } // 12時間ごとに再検証
})
return await response.json()
} catch (error) {
console.error('Failed to fetch products:', error)
return []
}
}
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
const baseURL = 'https://example.com'
// 静的ページ
const staticPages: MetadataRoute.Sitemap = [
{
url: `${baseURL}`,
lastModified: new Date(),
changeFrequency: 'daily',
priority: 1.0,
},
{
url: `${baseURL}/about`,
lastModified: new Date('2025-12-01'),
changeFrequency: 'monthly',
priority: 0.8,
},
{
url: `${baseURL}/blog`,
lastModified: new Date(),
changeFrequency: 'daily',
priority: 0.9,
},
]
// ブログ記事の動的URL
const articles = await getArticles()
const articlePages: MetadataRoute.Sitemap = articles.map((article: any) => ({
url: `${baseURL}/blog/${article.slug}`,
lastModified: new Date(article.updatedAt || article.createdAt),
changeFrequency: 'weekly' as const,
priority: 0.7,
}))
// 商品ページの動的URL
const products = await getProducts()
const productPages: MetadataRoute.Sitemap = products.map((product: any) => ({
url: `${baseURL}/products/${product.id}`,
lastModified: new Date(product.lastUpdated),
changeFrequency: 'weekly' as const,
priority: 0.6,
}))
// すべてのURLを統合
return [...staticPages, ...articlePages, ...productPages]
}
このアプローチの利点は、ビルド時にデータを取得するため、ページが生成される時点で最新の情報をsitemap.xmlに反映できることです。next: { revalidate: ... }オプションを使用することで、ISR(Incremental Static Regeneration)対応にすることも可能で、定期的に再ビルドすることなく、指定した間隔で自動的にデータを更新できます。
Next.jsでビルドを実行すると、.next/server/appディレクトリの下にsitemap.xmlファイルが自動生成されます。ローカル開発環境では、npm run buildを実行後、npm startでサーバーを起動し、http://localhost:3000/sitemap.xmlにアクセスすることで、生成されたXMLを確認できます。
生成された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>2025-12-23</lastmod>
<changefreq>daily</changefreq>
<priority>1.0</priority>
</url>
<url>
<loc>https://example.com/blog/my-first-post</loc>
<lastmod>2025-12-20</lastmod>
<changefreq>weekly</changefreq>
<priority>0.7</priority>
</url>
</urlset>
Next.js 12以前、またはPages Routerを使用しているプロジェクトでは、next-sitemapというコミュニティ製パッケージを使用することで、sitemap.xmlを生成できます。このパッケージは、ビルド時に自動的にpublic/sitemap.xmlを生成し、さらにrobots.txtも同時に作成できる便利なツールです。
インストールと基本設定:
npm install next-sitemap
# または
yarn add next-sitemap
インストール後、プロジェクトのルートにnext-sitemap.js設定ファイルを作成します:
// next-sitemap.js
module.exports = {
siteUrl: process.env.SITE_URL || 'https://example.com',
generateRobotsTxt: true, // robots.txtも自動生成
robotsTxtOptions: {
policies: [
{
userAgent: '*',
allow: '/',
disallow: ['/admin', '/private'],
},
{
userAgent: 'Googlebot',
allow: '/',
},
],
additionalSitemaps: [
'https://example.com/sitemap-additional.xml', // 追加のサイトマップ
],
},
outDir: './public', // 出力ディレクトリ
changefreq: 'daily', // デフォルトの更新頻度
priority: 0.7, // デフォルトの優先度
exclude: ['/admin', '/404', '/500'], // 除外するパス
}
ビルド時にsitemap.xmlを自動生成するため、package.jsonに以下のスクリプトを追加します:
{
"scripts": {
"build": "next build",
"postbuild": "next-sitemap",
"dev": "next dev"
}
}
postbuildスクリプトを設定することで、npm run buildを実行した後に自動的にnext-sitemapが実行され、sitemap.xmlが生成されます。
Pages Routerでも、ブログ記事やe-commerceサイトの商品など、動的に生成されるURLをsitemap.xmlに含める必要があります。next-sitemapでは、additionalPathsオプションを使用してこれを実現できます。
// next-sitemap.js
const { getAllArticles } = require('./lib/articles') // カスタム関数
module.exports = {
siteUrl: 'https://example.com',
generateRobotsTxt: true,
outDir: './public',
exclude: ['/admin', '/404', '/500'],
// 動的URLを追加する関数
additionalPaths: async (config) => {
// ビルド時にブログ記事を取得
const articles = await getAllArticles()
// 各記事をサイトマップに追加
const paths = articles.map((article) => ({
loc: `/blog/${article.slug}`, // URLパス
lastmod: article.updatedAt || article.createdAt, // 最終更新日
changefreq: 'weekly', // 更新頻度
priority: 0.7, // 優先度
}))
return paths
},
}
この方法を使用することで、ビルド時にデータベースやCMSから動的にデータを取得し、自動的にsitemap.xmlに反映できます。
sitemap.xmlは、特定のXML形式に従う必要があります。Googleの仕様に準拠することで、検索エンジンが確実にファイルを読み込める保証が得られます。
必須要素:
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
<loc>https://example.com/page</loc>
</url>
</urlset>
<?xml version="1.0" encoding="UTF-8"?>: XML宣言。ファイルがXML形式であることを示します<urlset>: すべてのURL要素を囲む必須のルート要素<url>: 個々のページを表す要素<loc>: ページの完全なURL。絶対URLで記載し、プロトコル(http://またはhttps://)を含む必要があります推奨要素:
<url>
<loc>https://example.com/blog/my-post</loc>
<lastmod>2025-12-20T10:30:00+00:00</lastmod>
<changefreq>weekly</changefreq>
<priority>0.8</priority>
</url>
<lastmod>: ページの最終更新日時。ISO 8601形式(YYYY-MM-DD または YYYY-MM-DDTHH:MM:SS+00:00)で記載します。Googleはこの情報を使用して、キャッシュを更新する必要があるかを判断します<changefreq>: ページの想定される更新頻度。Googleへの「このページはどのくらいの頻度で更新されるか」という情報提供です。指定可能な値はalways、hourly、daily、weekly、monthly、yearly、neverです。ただし、Googleはこの値を参考程度にしか扱わず、実際のクローリング頻度に反映されるとは限りません<priority>: サイト内での相対的な優先度を0.0~1.0の範囲で指定します。1.0が最高優先度です。デフォルト値は0.5ですGoogleのサイトマップ仕様には、以下のサイズ制限があります:
大規模なサイトでこれらの制限を超える場合は、サイトマップを複数のファイルに分割し、sitemap_index.xmlというインデックスファイルで一括管理します。
<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<sitemap>
<loc>https://example.com/sitemap-articles.xml</loc>
<lastmod>2025-12-23</lastmod>
</sitemap>
<sitemap>
<loc>https://example.com/sitemap-products.xml</loc>
<lastmod>2025-12-23</lastmod>
</sitemap>
<sitemap>
<loc>https://example.com/sitemap-pages.xml</loc>
<lastmod>2025-12-23</lastmod>
</sitemap>
</sitemapindex>
Next.jsで複数のサイトマップを生成する場合、App Routerでは複数のsitemap.tsファイルを作成するか、プログラムで複数のXMLファイルを生成する必要があります。
sitemap.xmlを作成しただけでは、検索エンジンボットが自動的にそれを発見するとは限りません。確実にGoogleやBingがサイトマップを認識するよう、robots.txtファイルでサイトマップの場所を明示することが推奨されています。
public/robots.txtに以下の行を追加します:
User-agent: *
Allow: /
Disallow: /admin
Disallow: /private
Sitemap: https://example.com/sitemap.xml
このファイルをWebサイトのルート(https://example.com/robots.txt)に配置することで、すべての検索エンジンボットに対してサイトマップの場所を告知できます。
App Routerを使用している場合、app/robots.tsファイルを作成することで、プログラムからrobots.txtを生成することもできます:
// app/robots.ts
import { MetadataRoute } from 'next'
export default function robots(): MetadataRoute.Robots {
return {
rules: {
userAgent: '*',
allow: '/',
disallow: ['/admin', '/private'],
},
sitemap: 'https://example.com/sitemap.xml',
}
}
sitemap.xmlを生成したら、Google Search Consoleに登録することで、Googleに対して明確にサイトマップの存在を伝えることができます。これにより、クローリング効率が向上し、新しいページや更新されたページがより素早くインデックスされるようになります。
登録手順:
Google Search Consoleにアクセス:https://search.google.com/search-console にアクセスし、Googleアカウントでログインします
プロパティを選択:登録したいドメインのプロパティを選択します。まだプロパティを追加していない場合は、「プロパティを追加」から新しいプロパティを作成します
左側メニューから「サイトマップ」を選択:ナビゲーションメニューの下部にある「インデックス」セクションから「サイトマップ」をクリックします
新しいサイトマップを追加:「新しいサイトマップの追加」ボタンをクリックし、サイトマップのURLを入力します。例:https://example.com/sitemap.xml
送信:URLを入力後、「送信」ボタンをクリックします
ステータスを確認:登録後、サイトマップのステータスが表示されます。「成功」と表示されれば、Googleがサイトマップを正常に読み込んでいることを示します
サイトマップの登録時に問題が発生する可能性があります:
「見つかりません」エラー:sitemap.xmlが正しいURLで配信されていない可能性があります。ブラウザで直接URLにアクセスし、XMLファイルが表示されるか確認してください
「形式が無効です」エラー:XMLの形式が正しくない可能性があります。XMLバリデーターを使用して、ファイルの構文をチェックしてください
インデックス登録されていないURL:サイトマップに含まれているURLがインデックスされていない場合、robots.txtで禁止されていないか、noindexメタタグが設定されていないか確認してください
前のセクションで説明した通り、AWS環境でNext.jsアプリケーションをデプロイする場合、生成されたsitemap.xmlを効率的に配信することが重要です。S3とCloudFrontを組み合わせることで、グローバルに高速なsitemap.xml配信が実現できます。
基本的な構成:
ビルド時にsitemap.xmlを生成:Next.jsのビルドプロセスで、App Routerならapp/sitemap.ts、Pages Routerならnext-sitemapを使用してsitemap.xmlを生成します
S3に静的ファイルをアップロード:生成されたsitemap.xmlを含む静的アセット(.next/staticやその他の静的ファイル)をS3バケットにアップロードします
CloudFrontでキャッシュ配信:CloudFrontをS3の前に配置し、sitemap.xmlをキャッシュすることで、すべてのリクエストがCloudFrontから返されるようになります
sitemap.xmlは静的ファイルであるため、積極的にキャッシュすることができます。ただし、サイトの更新頻度に応じて、適切なキャッシュ有効期限(TTL)を設定する必要があります。
# CloudFront キャッシュポリシーの例
Cache-Control: public, max-age=86400
# 24時間のキャッシュ
毎日サイトが更新される場合は、24時間(86400秒)のTTLを設定することで、新しいコンテンツが確実にGoogle側で認識されるようになります。変更頻度が低い場合は、より長いTTL(例えば7日間)を設定してもかまいません。
Next.jsのISR機能を使用している場合、サイトマップの再生成タイミングを適切に設定することが重要です。app/sitemap.tsでrevalidateオプションを設定することで、定期的にサイトマップを再生成できます:
export const revalidate = 86400 // 24時間ごとに再生成
この設定により、CloudFrontのキャッシュが有効期限に達すると同時に、オリジンサーバーで新しいsitemap.xmlが生成されるようになります。
正確な更新日時の記載:lastmodタグには、実際のページ更新日時を正確に記載することが重要です。古い日付を記載するとGoogleの信頼が低下し、クローリング頻度が減少する可能性があります
到達可能なURLのみを含める:sitemap.xmlに記載されているすべてのURLが、実際にアクセス可能である必要があります。削除されたページやリダイレクト先のURLを含めると、Googleから警告を受ける可能性があります
優先度の現実的な設定:priorityタグを使用する際は、実際のサイト構造を反映した値を設定してください。すべてのページに高い優先度を設定すると、Googleはこの値を無視するようになります
定期的な検証:Google Search Consoleを定期的に確認し、サイトマップのステータスに問題がないか、インデックス登録されていないURLがないか確認することが重要です
プロトコルの不一致:sitemap.xmlに記載するURLのプロトコル(http://またはhttps://)と、実際のWebサイトのプロトコルが一致していない場合、Googleがページを正しく認識できない可能性があります
ローカルパスの使用:sitemap.xmlには、相対パス(例:/blog/post)ではなく、完全な絶対URL(例:https://example.com/blog/post)を記載する必要があります
エンコーディングの問題:XMLファイルは必ずUTF-8でエンコードしてください。日本語を含む場合は、特に注意が必要です
過度な更新:sitemap.xmlを頻繁に更新する必要はありません。24時間~1週間程度の間隔で十分です。頻繁に更新すると、Googleのクローラーが頻繁にファイルをフェッチするようになり、不要なサーバー負荷が増加します
Next.jsでsitemap.xmlを静的生成することは、現代的なWebアプリケーション開発において欠かせないSEO対策です。App Routerを使用している場合は、app/sitemap.tsで公式対応された機能を活用できます。Pages Routerを使用している場合でも、next-sitemapパッケージで簡単に実装できます。
重要なのは、生成したsitemap.xmlをGoogle Search Consoleに登録することです。これにより、Googleに対してサイト構造を明確に伝え、クローリング効率を向上させることができます。さらに、AWS環境でCloudFrontとの組み合わせを活用することで、グローバルに高速なsitemap.xml配信が実現でき、SEOパフォーマンスの最適化につながります。
定期的にGoogle Search Consoleを確認し、サイトマップのステータスを監視することで、常にサイトの検索エンジン最適化を維持できます。これらの施策を組み合わせることで、検索エンジンからの流入を最大化し、Webサイトの成功を支えることができるのです。
記事数の多いカテゴリから探す