rewrites
Rewritesを使用すると、受信したリクエストパスを別の宛先パスにマップできます。
RewritesはURLプロキシとして機能し、宛先パスをマスクするため、ユーザーがサイト上の位置を変更していないように見えます。対照的に、redirectsは新しいページにリルートし、URLの変更を表示します。
Rewritesを使用するには、next.config.jsでrewritesキーを使用できます。
module.exports = {
async rewrites() {
return [
{
source: '/about',
destination: '/',
},
]
},
}Rewritesはクライアント側ルーティングに適用されます。上記の例では、<Link href="/about">に移動すると、URLを/aboutのままにしながら/からコンテンツが提供されます。
rewritesは非同期関数で、sourceおよびdestinationプロパティを持つオブジェクトを保持する配列またはオブジェクトの配列(下記参照)のいずれかを返すことが期待されます。
source:String- 受信したリクエストパスパターンです。destination:String- ルートする先のパスです。basePath:falseまたはundefined- falseの場合、マッチング時にbasePathが含まれません。外部rewritesのみに使用できます。locale:falseまたはundefined- マッチング時にlocaleを含めるかどうかです。hasはtype、key、valueプロパティを持つhasオブジェクトの配列です。missingはtype、key、valueプロパティを持つmissingオブジェクトの配列です。
rewrites関数が配列を返す場合、rewritesはファイルシステム(pagesおよび/publicファイル)をチェックした後、動的ルートの前に適用されます。rewrites関数が特定の形状のオブジェクト配列を返す場合、この動作はNext.jsのv10.1以降で変更および細かく制御できます。
module.exports = {
async rewrites() {
return {
beforeFiles: [
// これらのrewritesはheaders/redirectsの後にチェックされ、
// すべてのファイル(_next/publicファイルを含む)の前にチェックされるため、
// ページファイルをオーバーライドできます
{
source: '/some-page',
destination: '/somewhere-else',
has: [{ type: 'query', key: 'overrideMe' }],
},
],
afterFiles: [
// これらのrewritesはpages/publicファイルがチェックされた後、
// 動的ルートの前にチェックされます
{
source: '/non-existent',
destination: '/somewhere-else',
},
],
fallback: [
// これらのrewritesはpages/publicファイルと
// 動的ルートの両方がチェックされた後にチェックされます
{
source: '/:path*',
destination: `https://my-old-site.com/:path*`,
},
],
}
},
}補足:
beforeFilesのrewritesは、ソースがマッチした直後にファイルシステム/動的ルートをチェックしません。すべてのbeforeFilesがチェックされるまで続行されます。
Next.jsがチェックするルートの順序は以下の通りです。
- headersがチェック/適用されます
- redirectsがチェック/適用されます
- proxy
beforeFilesrewritesがチェック/適用されます- publicディレクトリの静的ファイル、
_next/staticファイル、および非動的ページがチェック/提供されます afterFilesrewritesがチェック/適用されます。これらのrewritesのいずれかがマッチした場合、各マッチ後に動的ルート/静的ファイルをチェックしますfallbackrewritesがチェック/適用されます。これらは404ページをレンダリングする前に、動的ルート/すべての静的アセットがチェックされた後に適用されます。getStaticPathsでfallback: true/'blocking'を使用する場合、next.config.jsで定義されたfallbackrewritesは実行されません。
Rewriteパラメータ
Rewriteでパラメータを使用する場合、destinationでパラメータが使用されていない場合、デフォルトではパラメータがクエリで渡されます。
module.exports = {
async rewrites() {
return [
{
source: '/old-about/:path*',
destination: '/about', // :pathパラメータはここで使用されていないため、自動的にクエリで渡されます
},
]
},
}パラメータが宛先で使用される場合、パラメータはクエリで自動的に渡されません。
module.exports = {
async rewrites() {
return [
{
source: '/docs/:path*',
destination: '/:path*', // :pathパラメータはここで使用されているため、クエリで自動的に渡されません
},
]
},
}destinationにパラメータを指定することで、destinationで既に使用されているパラメータをクエリで手動で渡すことができます。
module.exports = {
async rewrites() {
return [
{
source: '/:first/:second',
destination: '/:first?second=:second',
// :firstパラメータが宛先で使用されているため、:secondパラメータは
// 自動的にクエリに追加されませんが、上記に示すように手動で追加することはできます
},
]
},
}補足:自動静的最適化またはプリレンダリングからの静的ページのrewriteパラメータはハイドレーション後にクライアントで解析され、クエリで提供されます。
パスマッチング
パスマッチングが許可されています。例えば、/blog/:slugは/blog/hello-worldにマッチします(ネストされたパスはなし)。
module.exports = {
async rewrites() {
return [
{
source: '/blog/:slug',
destination: '/news/:slug', // マッチしたパラメータは宛先で使用できます
},
]
},
}ワイルドカードパスマッチング
ワイルドカードパスをマッチするには、パラメータの後に*を使用できます。例えば、/blog/:slug*は/blog/a/b/c/d/hello-worldにマッチします。
module.exports = {
async rewrites() {
return [
{
source: '/blog/:slug*',
destination: '/news/:slug*', // マッチしたパラメータは宛先で使用できます
},
]
},
}正規表現パスマッチング
正規表現パスをマッチするには、パラメータの後に括弧内に正規表現をラップできます。例えば、/blog/:slug(\\d{1,})は/blog/123にマッチしますが、/blog/abcにはマッチしません。
module.exports = {
async rewrites() {
return [
{
source: '/old-blog/:post(\\d{1,})',
destination: '/blog/:post', // マッチしたパラメータは宛先で使用できます
},
]
},
}以下の文字(、)、{、}、[、]、|、\、^、.、:、*、+、-、?、$は正規表現パスマッチングに使用されるため、sourceで非特殊値として使用する場合は、その前に\\を追加してエスケープする必要があります。
module.exports = {
async rewrites() {
return [
{
// これは`/english(default)/something`のリクエストにマッチします
source: '/english\\(default\\)/:slug',
destination: '/en-us/:slug',
},
]
},
}ヘッダー、Cookie、クエリマッチング
ヘッダー、Cookie、またはクエリ値もマッチする場合のみrewriteを適用するには、hasフィールドまたはmissingフィールドを使用できます。sourceと全てのhasアイテムはマッチし、全てのmissingアイテムはマッチしない必要があります。
hasおよびmissingアイテムは以下のフィールドを持つことができます。
type:String-header、cookie、host、またはqueryのいずれかである必要があります。key:String- マッチする選択されたタイプのキー。value:Stringまたはundefined- チェックする値。undefinedの場合、任意の値がマッチします。first-(?<paramName>.*)のような正規表現文字列を使用して、値の特定の部分をキャプチャできます。例えば、first-secondの値に対してfirst-(?<paramName>.*)が使用される場合、secondは: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',
// valueが提供され、名前付きキャプチャグループ(例:(?<page>home))を
// 使用していないため、page値は宛先で利用できません
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へのRewrite
例
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', // マッチしたパラメータは宛先で使用できます
},
]
},
}trailingSlash: trueを使用する場合は、sourceパラメータに末尾スラッシュを挿入する必要があります。宛先サーバーも末尾スラッシュが必要な場合は、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ルートをチェックした後、既存のウェブサイトにプロキシしてフォールバックするようにNext.jsを設定できます。
このように、より多くのページをNext.jsに移行する際にrewritesの設定を変更する必要がありません。
module.exports = {
async rewrites() {
return {
fallback: [
{
source: '/:path*',
destination: `https://custom-routes-proxying-endpoint.vercel.app/:path*`,
},
],
}
},
}basePathサポートのRewrite
basePathサポートをrewritesで活用する場合、rewriteにbasePath: falseを追加しない限り、各sourceとdestinationには自動的にbasePathが前置されます。
module.exports = {
basePath: '/docs',
async rewrites() {
return [
{
source: '/with-basePath', // 自動的に/docs/with-basePathになります
destination: '/another', // 自動的に/docs/anotherになります
},
{
// basePath: falseが設定されているため、/without-basePathに/docsを追加しません
// 注:内部rewriteの場合(例:`destination: '/another'`)は使用できません
source: '/without-basePath',
destination: 'https://example.com',
basePath: false,
},
]
},
}バージョン履歴
| バージョン | 変更内容 |
|---|---|
v13.3.0 | missing追加 |
v10.2.0 | has追加 |
v9.5.0 | ヘッダー追加 |