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
- マッチング時にロケールを含めるべきでないかどうか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*`,
},
],
}
},
}
Good to know:
beforeFiles
のrewritesは、source
がマッチした直後にファイルシステム/動的ルートをチェックせず、すべてのbeforeFiles
がチェックされるまで続行します。
Next.jsのルートがチェックされる順序は次のとおりです:
- headersがチェック/適用されます
- redirectsがチェック/適用されます
beforeFiles
のrewritesがチェック/適用されます- publicディレクトリからの静的ファイル、
_next/static
ファイル、および非動的ページがチェック/提供されます afterFiles
のrewritesがチェック/適用されます。これらのrewritesのいずれかがマッチした場合、各マッチの後に動的ルート/静的ファイルをチェックしますfallback
のrewritesがチェック/適用されます。これらは404ページをレンダリングする前、および動的ルート/すべての静的アセットがチェックされた後に適用されます。getStaticPaths
でfallback: true/'blocking'を使用する場合、next.config.js
で定義されたfallbackrewrites
は実行されません。
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からの静的ページのパラメータは、ハイドレーション後にクライアントで解析され、クエリで提供されます。
パスマッチング
パスマッチングが許可されています。たとえば、/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',
},
]
},
}
ヘッダー、クッキー、およびクエリのマッチング
ヘッダー、クッキー、またはクエリの値が一致する場合にのみrewriteをマッチさせるには、has
フィールドを使用するか、missing
フィールドを使用して一致しない場合にrewriteを適用できます。source
とすべてのhas
アイテムが一致し、すべてのmissing
アイテムが一致しない場合にrewriteが適用されます。
has
とmissing
アイテムには次のフィールドがあります:
type
:String
-header
、cookie
、host
、またはquery
のいずれかである必要がありますkey
:String
- 一致させるために選択されたタイプのキーですvalue
:String
またはundefined
- チェックする値です。undefinedの場合、任意の値が一致します。特定の部分をキャプチャするために正規表現のような文字列を使用できます。たとえば、値first-(?<paramName>.*)
がfirst-second
に使用される場合、second
は:paramName
でdestinationで使用できます。
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',
},
// source、query、および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への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', // マッチしたパラメータはdestinationで使用できます
},
]
},
}
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のすべてのルートをチェックした後、既存の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が追加されません
// 注意:これは内部のrewritesには使用できません。例:`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
にロケールをプレフィックスする必要があります。
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`がdefaultLocaleであるため、`/`にマッチします
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.0 | missing が追加されました |
v10.2.0 | has が追加されました |
v9.5.0 | Headersが追加されました |