メインコンテンツまでスキップ

rewrites

Rewritesは、受信するリクエストパスを別のサーバー先のパスにマッピングすることを可能にします。

RewritesはURLプロキシとして機能し、サーバー先のパスを隠し、ユーザーがサイトの場所を変更していないように見せます。これに対して、redirectsは新しいページにリダイレクトし、URLが変更されたことを表示します。

Rewritesを使用するには、next.config.jsの中でrewritesキーを使用します:

next.config.js
module.exports = {
async rewrites() {
return [
{
source: '/about',
destination: '/',
},
]
},
}

Rewritesはクライアントサイドルーティングに適用されます。上記の例では、<Link href="/about">にrewriteが適用されます。

rewritesは、sourceおよびdestinationプロパティを持つオブジェクトを含む配列または配列のオブジェクト(下記参照)を返すことを期待する非同期関数です:

  • source: String - 受信するリクエストパスのパターン
  • destination: String - リアウト先のパス
  • basePath: falseまたはundefined - falseの場合、マッチング時にbasePathは含まれません。外部のrewrites専用です
  • locale: falseまたはundefined - localeが含まれないかどうかを指定
  • hastypekeyおよびvalueプロパティを持つhas objectsの配列
  • missingtypekeyおよびvalueプロパティを持つmissing objectsの配列

rewrites関数が配列を返す場合、rewriteはファイルシステム(ページおよび/publicファイル)を確認した後、動的ルーティングの前に適用されます。rewrites関数が特定の形状を持つ配列のオブジェクトを返す場合、この動作が変更され、より細かく制御できます。これはNext.js v10.1からです:

next.config.js
module.exports = {
async rewrites() {
return {
beforeFiles: [
// このrewriteは、ヘッダー/リダイレクトのあと、
// _next/publicファイルを含むすべてのファイルの前に確認されるため、
// ページファイルを上書きすることができます
{
source: '/some-page',
destination: '/somewhere-else',
has: [{ type: 'query', key: 'overrideMe' }],
},
],
afterFiles: [
// このrewriteは、ページ/公開ファイルの後で確認され、
// 動的ルートの前に確認されます
{
source: '/non-existent',
destination: '/somewhere-else',
},
],
fallback: [
// このrewriteは、ページ/公開ファイルおよび動的ルートの
// 両方を確認した後に確認されます
{
source: '/:path*',
destination: `https://my-old-site.com/:path*`,
},
],
}
},
}

Good to know: beforeFiles内のrewriteは、ソースが一致した直後にファイルシステム/動的ルートを確認せず、すべてのbeforeFilesが確認されるまで続行します。

Next.jsルートが確認される順序は以下のとおりです:

  1. headersが確認され、適用されます
  2. redirectsが確認され、適用されます
  3. beforeFilesのrewriteが確認され、適用されます
  4. public directoryの静的ファイル、_next/staticファイル、動的でないページが確認され、提供されます
  5. afterFilesのrewriteが確認され、適用され、これらのrewriteが一致した場合、動的ルート/静的ファイルは各一致後に確認されます
  6. fallbackのrewriteが確認され、適用されます。これらは404ページをレンダリングする前、そして動的ルート/すべての静的アセットが確認された後に適用されます。getStaticPathsfallback: true/'blocking'を使用する場合、next.config.jsで定義されたrewritesは実行されません。

Rewriteパラメータ

rewriteでパラメータを使用する際にdestinationで使用されていない場合、パラメータはデフォルトでクエリに渡されます。

next.config.js
module.exports = {
async rewrites() {
return [
{
source: '/old-about/:path*',
destination: '/about', // :pathパラメータはここで使用されていないため、クエリに自動的に渡されます
},
]
},
}

パラメータがdestinationで使用される場合、パラメータはクエリに自動的に渡されません。

next.config.js
module.exports = {
async rewrites() {
return [
{
source: '/docs/:path*',
destination: '/:path*', // :pathパラメータはここで使用されているため、クエリに自動的に渡されません
},
]
},
}

destinationで既に使用されている場合でも、クエリでクエリを指定することで手動でパラメータを渡すことができます。

next.config.js
module.exports = {
async rewrites() {
return [
{
source: '/:first/:second',
destination: '/:first?second=:second',
// :firstパラメータはdestinationで使用されるため、:secondパラメータ
// はクエリに自動的に追加されません。ただし、上記のように手動で追加可能です
},
]
},
}

Good to know: Automatic Static Optimizationまたはprerenderingからのrewritesパラメータの静的ページは、ハイドレーション後にクライアント上で解析され、クエリで提供されます。

パスマッチング

パスのマッチングが許可されています。たとえば/blog/:slug/blog/hello-worldにマッチします(ネストされたパスではありません):

next.config.js
module.exports = {
async rewrites() {
return [
{
source: '/blog/:slug',
destination: '/news/:slug', // マッチしたパラメータはdestinationで使用できます
},
]
},
}

ワイルドカードパスマッチング

ワイルドカードパスをマッチングするには、パラメータの後に*を使用します。たとえば/blog/:slug*/blog/a/b/c/d/hello-worldにマッチします:

next.config.js
module.exports = {
async rewrites() {
return [
{
source: '/blog/:slug*',
destination: '/news/:slug*', // マッチしたパラメータはdestinationで使用できます
},
]
},
}

正規表現パスマッチング

正規表現パスをマッチングするには、パラメータのあとのカッコ内に正規表現をラップします。たとえば/blog/:slug(\\d{1,})/blog/123にマッチしますが、/blog/abcにはマッチしません:

next.config.js
module.exports = {
async rewrites() {
return [
{
source: '/old-blog/:post(\\d{1,})',
destination: '/blog/:post', // マッチしたパラメータはdestinationで使用できます
},
]
},
}

次の文字は正規表現パスマッチングに使用されるため、sourceで非特別な値として使用する場合は、\\を追加してエスケープする必要があります:(){}[]|\^.:*+-?$

next.config.js
module.exports = {
async rewrites() {
return [
{
// このリクエストは`/english(default)/something`にマッチします
source: '/english\\(default\\)/:slug',
destination: '/en-us/:slug',
},
]
},
}

ヘッダー、Cookie、またはクエリ値が一致する場合にのみrewriteをマッチさせるために、hasフィールドまたはmissingフィールドを使用できます。rewriteが適用されるためには、sourceとすべてのhas項目が一致し、すべてのmissing項目が一致しない必要があります。

hasmissing項目には次のフィールドがあります:

  • type: String - headercookiehost、またはqueryのいずれかでなければなりません
  • key: String - 選択したタイプから一致させるキー
  • value: Stringまたはundefined - チェックする値で、未定義の場合は任意の値が一致します。正規表現のような文字列は値の特定の部分をキャプチャするために使用できます。たとえば、値first-(?<paramName>.*)first-secondに使用されている場合、seconddestination:paramNameとして使用できます。
next.config.js
module.exports = {
async rewrites() {
return [
// ヘッダー `x-rewrite-me`が存在する場合、
// このrewriteが適用されます
{
source: '/:path*',
has: [
{
type: 'header',
key: 'x-rewrite-me',
},
],
destination: '/another-page',
},
// ヘッダー `x-rewrite-me`が存在しない場合、
// このrewriteが適用されます
{
source: '/:path*',
missing: [
{
type: 'header',
key: 'x-rewrite-me',
},
],
destination: '/another-page',
},
// ソース、クエリ、Cookieがマッチする場合、
// このrewriteが適用されます
{
source: '/specific/:path*',
has: [
{
type: 'query',
key: 'page',
// 値が提供され、名前付きキャプチャグループを
// 使用しないため、page値はdestinationで利用可能になりません
// 例:(?<page>home)
value: 'home',
},
{
type: 'cookie',
key: 'authorized',
value: 'true',
},
],
destination: '/:path*/home',
},
// ヘッダー `x-authorized` が存在し、
// マッチする値が含まれている場合、このrewriteが適用されます
{
source: '/:path*',
has: [
{
type: 'header',
key: 'x-authorized',
value: '(?<authorized>yes|true)',
},
],
destination: '/home?authorized=:authorized',
},
// ホストが `example.com` の場合、
// このrewriteが適用されます
{
source: '/:path*',
has: [
{
type: 'host',
value: 'example.com',
},
],
destination: '/another-page',
},
]
},
}

外部URLへのリライト

Rewritesでは外部URLへのrewriteが可能です。これはNext.jsを段階的に採用するのに特に便利です。以下は、メインアプリの/blogルートを外部サイトにリダイレクトするrewriteの例です。

next.config.js
module.exports = {
async rewrites() {
return [
{
source: '/blog',
destination: 'https://example.com/blog',
},
{
source: '/blog/:slug',
destination: 'https://example.com/blog/:slug', // マッチしたパラメータはdestinationで使用できます
},
]
},
}

trailingSlash: trueを使用している場合、sourceパラメータにトレーリングスラッシュを挿入する必要があります。destinationサーバーもトレーリングスラッシュを期待している場合は、destinationパラメータにも含めるべきです。

next.config.js
module.exports = {
trailingSlash: true,
async rewrites() {
return [
{
source: '/blog/',
destination: 'https://example.com/blog/',
},
{
source: '/blog/:path*/',
destination: 'https://example.com/blog/:path*/',
},
]
},
}

Next.jsの漸進的採用

Next.jsのすべてのルートを確認した後、既存のWebサイトへのプロキシにフォールバックさせることもできます。

この方法を使用することで、より多くのページをNext.jsに移行するときにrewrite設定を変更する必要がありません。

next.config.js
module.exports = {
async rewrites() {
return {
fallback: [
{
source: '/:path*',
destination: `https://custom-routes-proxying-endpoint.vercel.app/:path*`,
},
],
}
},
}

basePathサポートのあるrewrites

rewritesでbasePathサポートを活用すると、sourcedestinationの各項目にbasePathが自動的にプレフィックスされます。ただし、rewriteにbasePath: falseを追加すると除外されます:

next.config.js
module.exports = {
basePath: '/docs',

async rewrites() {
return [
{
source: '/with-basePath', // 自動的に/docs/with-basePathになります
destination: '/another', // 自動的に/docs/anotherになります
},
{
// basePath: falseが設定されているため、/without-basePathに/docsを追加しません
// 注意:これは内部リライトには使用できません。たとえば、`destination: '/another'`
source: '/without-basePath',
destination: 'https://example.com',
basePath: false,
},
]
},
}

i18nサポートを活用したrewrites

rewritesでi18nサポートを活用すると、sourcedestinationは設定されたlocalesを処理するために自動的にプレフィックスされます。ただし、rewriteにlocale: falseを追加すると除外されます。locale: falseを使用する場合は、正しく一致させるためにsourcedestinationにlocaleをプレフィックスする必要があります。

next.config.js
module.exports = {
i18n: {
locales: ['en', 'fr', 'de'],
defaultLocale: 'en',
},

async rewrites() {
return [
{
source: '/with-locale', // すべてのlocaleを自動的に処理します
destination: '/another', // localeを自動的に渡します
},
{
// locale: falseが設定されているため、localeは自動的に処理されません
source: '/nl/with-locale-manual',
destination: '/nl/another',
locale: false,
},
{
// `en`がdefaultLocaleであるため`/`に一致します
source: '/en',
destination: '/en/another',
locale: false,
},
{
// locale: falseが設定されている場合でもすべてのlocaleに一致させることができます
source: '/:locale/api-alias/:path*',
destination: '/api/:path*',
locale: false,
},
{
// これは/(en|fr|de)/(.*)に変換されるため、トップレベルの
// `/` や `/fr`ルートには/:path*のように一致しません
source: '/(.*)',
destination: '/another',
},
]
},
}

バージョン履歴

Version変化
v13.3.0missingが追加されました
v10.2.0hasが追加されました
v9.5.0ヘッダーが追加されました