rewrites
Rewritesは、受信するリクエストパスを別のサーバー先のパスにマッピングすることを可能にします。
RewritesはURLプロキシとして機能し、サーバー先のパスを隠し、ユーザーがサイトの場所を変更していないように見せます。これに対して、redirectsは新しいページにリダイレクトし、URLが変更されたことを表示します。
Rewritesを使用するには、next.config.js
の中でrewrites
キーを使用します:
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が含まれないかどうかを指定has
はtype
、key
およびvalue
プロパティを持つhas objectsの配列missing
はtype
、key
およびvalue
プロパティを持つmissing objectsの配列
rewrites
関数が配列を返す場合、rewriteはファイルシステム(ページおよび/public
ファイル)を確認した後、動的ルーティングの前に適用されます。rewrites
関数が特定の形状を持つ配列のオブジェクトを返す場合、この動作が変更され、より細かく制御できます。これはNext.js v10.1
からです:
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ルートが確認される順序は以下のとおりです:
- headersが確認され、適用されます
- redirectsが確認され、適用されます
beforeFiles
のrewriteが確認され、適用されます- public directoryの静的ファイル、
_next/static
ファイル、動的でないページが確認され、提供されます afterFiles
のrewriteが確認され、適用され、これらのrewriteが一致した場合、動的ルート/静的ファイルは各一致後に確認されますfallback
のrewriteが確認され、適用されます。これらは404ページをレンダリングする前、そして動的ルート/すべての静的アセットが確認された後に適用されます。getStaticPaths
でfallback: true/'blocking'を使用する場合、next.config.js
で定義されたrewrites
は実行されません。
Rewriteパラメータ
rewriteでパラメータを使用する際にdestination
で使用されていない場合、パラメータはデフォルトでクエリに渡されます。
module.exports = {
async rewrites() {
return [
{
source: '/old-about/:path*',
destination: '/about', // :pathパラメータはここで使用されていないため、クエリに自動的に渡されます
},
]
},
}
パラメータがdestination
で使用される場合、パラメータはクエリに自動的に渡されません。
module.exports = {
async rewrites() {
return [
{
source: '/docs/:path*',
destination: '/:path*', // :pathパラメータはここで使用されているため、クエリに自動的に渡されません
},
]
},
}
destination
で既に使用されている場合でも、クエリでクエリを指定することで手動でパラメータを渡すことができます。
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
にマッチします(ネストされたパスではありません):
module.exports = {
async rewrites() {
return [
{
source: '/blog/:slug',
destination: '/news/:slug', // マッチしたパラメータはdestinationで使用できます
},
]
},
}
ワイルドカードパスマッチング
ワイルドカードパスをマッチングするには、パラメータの後に*
を使用します。たとえば/blog/:slug*
は/blog/a/b/c/d/hello-world
にマッチします:
module.exports = {
async rewrites() {
return [
{
source: '/blog/:slug*',
destination: '/news/:slug*', // マッチしたパラメータはdestinationで使用できます
},
]
},
}
正規表現パスマッチング
正規表現パスをマッチングするには、パラメータのあとのカッコ内に正規表現をラップします。たとえば/blog/:slug(\\d{1,})
は/blog/123
にマッチしますが、/blog/abc
にはマッチしません:
module.exports = {
async rewrites() {
return [
{
source: '/old-blog/:post(\\d{1,})',
destination: '/blog/:post', // マッチしたパラメータはdestinationで使用できます
},
]
},
}
次の文字は正規表現パスマッチングに使用されるため、source
で非特別な値として使用する場合は、\\
を追加してエスケープする必要があります:(
、)
、{
、}
、[
、]
、|
、\
、^
、.
、:
、*
、+
、-
、?
、$
module.exports = {
async rewrites() {
return [
{
// このリクエストは`/english(default)/something`にマッチします
source: '/english\\(default\\)/:slug',
destination: '/en-us/:slug',
},
]
},
}
ヘッダー、Cookie、クエリのマッチング
ヘッダー、Cookie、またはクエリ値が一致する場合にのみrewriteをマッチさせるために、has
フィールドまたはmissing
フィールドを使用できます。rewriteが適用されるためには、source
とすべてのhas
項目が一致し、すべてのmissing
項目が一致しない必要があります。
has
とmissing
項目には次のフィールドがあります:
type
:String
-header
、cookie
、host
、またはquery
のいずれかでなければなりませんkey
:String
- 選択したタイプから一致させるキーvalue
:String
またはundefined
- チェックする値で、未定義の場合は任意の値が一致します。正規表現のような文字列は値の特定の部分をキャプチャするために使用できます。たとえば、値first-(?<paramName>.*)
がfirst-second
に使用されている場合、second
はdestination
で:paramName
として使用できます。
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の例です。
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
パラメータにも含めるべきです。
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設定を変更する必要がありません。
module.exports = {
async rewrites() {
return {
fallback: [
{
source: '/:path*',
destination: `https://custom-routes-proxying-endpoint.vercel.app/:path*`,
},
],
}
},
}
basePathサポートのあるrewrites
rewritesでbasePath
サポートを活用すると、source
とdestination
の各項目にbasePath
が自動的にプレフィックスされます。ただし、rewriteにbasePath: false
を追加すると除外されます:
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
サポートを活用すると、source
とdestination
は設定されたlocales
を処理するために自動的にプレフィックスされます。ただし、rewriteにlocale: false
を追加すると除外されます。locale: false
を使用する場合は、正しく一致させるためにsource
とdestination
にlocaleをプレフィックスする必要があります。
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.0 | missing が追加されました |
v10.2.0 | has が追加されました |
v9.5.0 | ヘッダーが追加されました |