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

rewrites

rewritesを使用すると、リクエストパスを異なる宛先パスにマッピングできます。

rewritesはURLプロキシとして動作し、宛先パスを隠して、ユーザーがサイト上で位置を変えていないように見せます。それに対して、redirectsは新しいページにリダイレクトし、URLの変更を表示します。

rewritesを使用するには、next.config.jsrewritesキーを使用します:

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

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

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

  • source: String - リクエストパスパターンです
  • destination: String - ルート先のパスです
  • basePath: falseまたはundefined - falseの場合、basePathは一致に含まれません。外部のrewritesのみに使用されます
  • locale: falseまたはundefined - 一致する際にlocaleを含めるべきかどうか
  • hastypekeyおよびvalueプロパティを持つhas オブジェクトの配列です
  • missingtypekeyおよびvalueプロパティを持つmissing オブジェクトの配列です

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

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

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

Next.jsルートのチェック順序は以下のとおりです:

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

リライトパラメータ

リライトでパラメータを使用する場合、パラメータが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でパラメータがすでに使用されている場合、クエリで手動でパラメータを渡すことはできます。クエリをdestinationで指定します。

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

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

パスマッチング

パスマッチングは許可されています。例えば、/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',
},
]
},
}

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

hasおよびmissing項目は、以下のフィールドを持つことができます:

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

リライトを外部URLに変更する

rewritesを使用すると、外部URLにリライトできます。これはNext.jsを徐々に導入するのに特に便利です。以下は、メインアプリの/blogルートを外部サイトにリダイレクトするための例です。

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パラメータにも含めるべきです。

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のルートをすべてチェックした後、既存のウェブサイトへのプロキシにフォールバックすることもできます。

この方法を使用すると、より多くのページをNext.jsに移行する際に、リライトの構成を変更する必要がありません。

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

basePathサポートを伴うリライト

rewritesでbasePathサポートを利用すると、basePath: falseをリライトに追加しない限り、各sourcedestinationは自動的にbasePathでプレフィックスされます:

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でi18nサポートを利用すると、locale: falseをリライトに追加しない限り、それぞれのsourcedestinationは、設定されたlocalesを処理するために自動的にプレフィックスされます。locale: falseを使用する場合は、正しく一致するように、sourcedestinationにロケールをプレフィックスする必要があります。

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

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

バージョン履歴

バージョン変更点
v13.3.0missingが追加されました
v10.2.0hasが追加されました
v9.5.0ヘッダーが追加されました