rewrites
リライトを使用すると、受信リクエストパスを別の宛先パスにマッピングできます。
リライトはURLプロキシとして機能し、宛先パスを隠すため、ユーザーがサイト上の場所を変更していないように見えます。対照的に、リダイレクトは新しいページに再ルーティングし、URLの変更が表示されます。
リライトを使用するには、next.config.js
でrewrites
キーを使用します。
module.exports = {
async rewrites() {
return [
{
source: '/about',
destination: '/',
},
]
},
}
リライトはクライアントサイドルーティングに適用されます。上記の例では、<Link href="/about">
にリライトが適用されます。
rewrites
は、source
とdestination
プロパティを持つオブジェクトを保持する配列または配列のオブジェクト(下記参照)を返すことを期待する非同期関数です。
source
:String
- 受信リクエストのパスパターンです。destination
:String
- ルーティングしたいパスです。basePath
:false
またはundefined
- falseの場合、マッチング時にbasePathは含まれません。外部リライトでのみ使用できます。locale
:false
またはundefined
- マッチング時にロケールを含めるべきではないかどうか。has
は、type
、key
、およびvalue
プロパティを持つhasオブジェクトの配列です。missing
は、type
、key
、およびvalue
プロパティを持つmissingオブジェクトの配列です。
rewrites
関数が配列を返す場合、リライトはファイルシステム(ページと/public
ファイル)のチェック後、ダイナミックルートの前に適用されます。rewrites
関数が特定の形状の配列のオブジェクトを返す場合、Next.jsのv10.1
以降、この動作を変更し、より細かく制御できます。
module.exports = {
async rewrites() {
return {
beforeFiles: [
// These rewrites are checked after headers/redirects
// and before all files including _next/public files which
// allows overriding page files
{
source: '/some-page',
destination: '/somewhere-else',
has: [{ type: 'query', key: 'overrideMe' }],
},
],
afterFiles: [
// These rewrites are checked after pages/public files
// are checked but before dynamic routes
{
source: '/non-existent',
destination: '/somewhere-else',
},
],
fallback: [
// These rewrites are checked after both pages/public files
// and dynamic routes are checked
{
source: '/:path*',
destination: `https://my-old-site.com/:path*`,
},
],
}
},
}
補足:
beforeFiles
のリライトは、ソースにマッチした後すぐにファイルシステム/ダイナミックルートをチェックせず、すべてのbeforeFiles
がチェックされるまで続行します。
Next.jsのルートがチェックされる順序は次のとおりです。
- ヘッダーがチェック/適用されます。
- リダイレクトがチェック/適用されます。
beforeFiles
のリライトがチェック/適用されます。- publicディレクトリからの静的ファイル、
_next/static
ファイル、および非ダイナミックページがチェック/提供されます。 afterFiles
のリライトがチェック/適用されます。これらのリライトのいずれかが一致した場合、一致するたびにダイナミックルート/静的ファイルをチェックします。fallback
のリライトがチェック/適用されます。これらは404ページをレンダリングする前、およびダイナミックルート/すべての静的アセットがチェックされた後に適用されます。getStaticPaths
でfallback: true/'blocking'を使用する場合、next.config.js
で定義されたフォールバックrewrites
は実行されません。
リライトパラメータ
リライトでパラメータを使用する場合、destination
でどのパラメータも使用されていない場合、パラメータはデフォルトでクエリに渡されます。
module.exports = {
async rewrites() {
return [
{
source: '/old-about/:path*',
destination: '/about', // The :path parameter isn't used here so will be automatically passed in the query
},
]
},
}
パラメータが宛先で使用されている場合、どのパラメータも自動的にクエリに渡されることはありません。
module.exports = {
async rewrites() {
return [
{
source: '/docs/:path*',
destination: '/:path*', // The :path parameter is used here so will not be automatically passed in the query
},
]
},
}
パラメータが宛先で既に使用されている場合でも、destination
でクエリを指定することで、パラメータをクエリに手動で渡すことができます。
module.exports = {
async rewrites() {
return [
{
source: '/:first/:second',
destination: '/:first?second=:second',
// Since the :first parameter is used in the destination the :second parameter
// will not automatically be added in the query although we can manually add it
// as shown above
},
]
},
}
補足: 自動静的最適化またはプリレンダリングによって生成された静的ページのリライトパラメータは、ハイドレーション後にクライアントでパースされ、クエリとして提供されます。
パスマッチング
パスの一致が許可されます。たとえば、/blog/:slug
は/blog/hello-world
と一致します(ネストされたパスは除く)。
module.exports = {
async rewrites() {
return [
{
source: '/blog/:slug',
destination: '/news/:slug', // Matched parameters can be used in the destination
},
]
},
}
ワイルドカードパスマッチング
ワイルドカードパスと一致させるには、パラメータの後に*
を使用します。たとえば、/blog/:slug*
は/blog/a/b/c/d/hello-world
と一致します。
module.exports = {
async rewrites() {
return [
{
source: '/blog/:slug*',
destination: '/news/:slug*', // Matched parameters can be used in the destination
},
]
},
}
正規表現パスマッチング
正規表現パスと一致させるには、パラメータの後に正規表現を括弧で囲みます。たとえば、/blog/:slug(\\d{1,})
は/blog/123
と一致しますが、/blog/abc
とは一致しません。
module.exports = {
async rewrites() {
return [
{
source: '/old-blog/:post(\\d{1,})',
destination: '/blog/:post', // Matched parameters can be used in the destination
},
]
},
}
(
, )
, {
, }
, [
, ]
, |
, \
, ^
, .
, :
, *
, +
, -
, ?
, $
の文字は正規表現のパスマッチングに使用されるため、source
で特殊でない値として使用する場合は、それらの前に\\
を追加してエスケープする必要があります。
module.exports = {
async rewrites() {
return [
{
// this will match `/english(default)/something` being requested
source: '/english\\(default\\)/:slug',
destination: '/en-us/:slug',
},
]
},
}
ヘッダー、Cookie、およびクエリのマッチング
ヘッダー、Cookie、またはクエリの値がhas
フィールドと一致するか、missing
フィールドと一致しない場合にのみリライトを一致させるには、has
フィールドまたはmissing
フィールドを使用できます。リライトが適用されるには、source
とすべてのhas
項目が一致し、すべてのmissing
項目が一致しない必要があります。
has
とmissing
項目には、以下のフィールドを含めることができます。
type
:String
-header
、cookie
、host
、またはquery
のいずれかである必要があります。key
:String
- 選択されたタイプから一致させるキー。value
:String
またはundefined
- チェックする値。undefinedの場合、任意の値が一致します。値の特定の部分をキャプチャするために、正規表現のような文字列を使用できます。例えば、値first-(?<paramName>.*)
がfirst-second
に使用された場合、second
は:paramName
を使って宛先で使用可能になります。
module.exports = {
async rewrites() {
return [
// if the header `x-rewrite-me` is present,
// this rewrite will be applied
{
source: '/:path*',
has: [
{
type: 'header',
key: 'x-rewrite-me',
},
],
destination: '/another-page',
},
// if the header `x-rewrite-me` is not present,
// this rewrite will be applied
{
source: '/:path*',
missing: [
{
type: 'header',
key: 'x-rewrite-me',
},
],
destination: '/another-page',
},
// if the source, query, and cookie are matched,
// this rewrite will be applied
{
source: '/specific/:path*',
has: [
{
type: 'query',
key: 'page',
// the page value will not be available in the
// destination since value is provided and doesn't
// use a named capture group e.g. (?<page>home)
value: 'home',
},
{
type: 'cookie',
key: 'authorized',
value: 'true',
},
],
destination: '/:path*/home',
},
// if the header `x-authorized` is present and
// contains a matching value, this rewrite will be applied
{
source: '/:path*',
has: [
{
type: 'header',
key: 'x-authorized',
value: '(?<authorized>yes|true)',
},
],
destination: '/home?authorized=:authorized',
},
// if the host is `example.com`,
// this rewrite will be applied
{
source: '/:path*',
has: [
{
type: 'host',
value: 'example.com',
},
],
destination: '/another-page',
},
]
},
}
外部URLへのリライト
リライトを使用すると、外部URLにリライトできます。これは、Next.jsを段階的に採用する場合に特に便利です。以下は、メインアプリの/blog
ルートを外部サイトにリダイレクトするためのリライトの例です。
module.exports = {
async rewrites() {
return [
{
source: '/blog',
destination: 'https://example.com/blog',
},
{
source: '/blog/:slug',
destination: 'https://example.com/blog/:slug', // Matched parameters can be used in the 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のすべてのルートをチェックした後、既存のウェブサイトへのプロキシにフォールバックすることもできます。
これにより、さらに多くのページをNext.jsに移行する際に、リライトの設定を変更する必要がなくなります。
module.exports = {
async rewrites() {
return {
fallback: [
{
source: '/:path*',
destination: `https://custom-routes-proxying-endpoint.vercel.app/:path*`,
},
],
}
},
}
basePathをサポートするリライト
リライトでbasePath
サポートを利用する場合、basePath: false
をリライトに追加しない限り、各source
とdestination
には自動的にbasePath
がプレフィックスとして付加されます。
module.exports = {
basePath: '/docs',
async rewrites() {
return [
{
source: '/with-basePath', // automatically becomes /docs/with-basePath
destination: '/another', // automatically becomes /docs/another
},
{
// does not add /docs to /without-basePath since basePath: false is set
// Note: this can not be used for internal rewrites e.g. `destination: '/another'`
source: '/without-basePath',
destination: 'https://example.com',
basePath: false,
},
]
},
}
i18nをサポートするリライト
リライトでi18n
サポートを利用する場合、locale: false
をリライトに追加しない限り、各source
とdestination
には設定されたlocales
を処理するために自動的にプレフィックスが付加されます。locale: false
を使用する場合、正しく一致させるには、source
とdestination
にロケールをプレフィックスとして付加する必要があります。
module.exports = {
i18n: {
locales: ['en', 'fr', 'de'],
defaultLocale: 'en',
},
async rewrites() {
return [
{
source: '/with-locale', // automatically handles all locales
destination: '/another', // automatically passes the locale on
},
{
// does not handle locales automatically since locale: false is set
source: '/nl/with-locale-manual',
destination: '/nl/another',
locale: false,
},
{
// this matches '/' since `en` is the defaultLocale
source: '/en',
destination: '/en/another',
locale: false,
},
{
// it's possible to match all locales even when locale: false is set
source: '/:locale/api-alias/:path*',
destination: '/api/:path*',
locale: false,
},
{
// this gets converted to /(en|fr|de)/(.*) so will not match the top-level
// `/` or `/fr` routes like /:path* would
source: '/(.*)',
destination: '/another',
},
]
},
}
バージョン履歴
バージョン | 変更点 |
---|---|
v13.3.0 | missing が追加されました。 |
v10.2.0 | has が追加されました。 |
v9.5.0 | ヘッダーが追加されました。 |
この情報はお役に立ちましたか?