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

redirects

リダイレクトは、受信するリクエストパスを別の宛先パスにリダイレクトできます。

リダイレクトを使用するには、next.config.jsredirectsキーを使用します:

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

redirectsは非同期関数で、sourcedestination、およびpermanentプロパティを持つオブジェクトを含む配列を返すことが期待されています:

  • sourceは受信するリクエストパスパターンです
  • destinationはルーティングするパスです
  • permanenttrueまたはfalseです。trueの場合はクライアント/検索エンジンにリダイレクトを永遠にキャッシュするよう指示する308ステータスコードを使用し、falseの場合は一時的でキャッシュされない307ステータスコードを使用します

なぜNext.jsは307と308を使用するのですか? 伝統的に302は一時的なリダイレクト、301は永続的なリダイレクトとして使用されていましたが、多くのブラウザはリダイレクトのリクエストメソッドを元のメソッドに関係なくGETに変更しました。たとえば、ブラウザがPOST /v1/usersにリクエストし、ステータスコード302と共に場所が/v2/usersと返された場合、次のリクエストが期待されるPOST /v2/usersではなくGET /v2/usersになるかもしれません。Next.jsは307の一時的なリダイレクトと308の永続的なリダイレクトステータスコードを使用して、使用されたリクエストメソッドを明示的に保持します。

  • basePathfalseまたはundefined - falseの場合、外部リダイレクトのみに使用され、マッチング時にbasePathは含まれません。
  • localefalseまたはundefined - ロケールが一致する際に含まれないかどうか。
  • hastypekeyvalueプロパティを持つhasオブジェクトの配列です。
  • missingtypekeyvalueプロパティを持つmissingオブジェクトの配列です。

リダイレクトはファイルシステムの前にチェックされ、ページや/publicファイルが含まれます。

Pages Routerを使用する場合、リダイレクトはMiddlewareが存在し、パスと一致する場合を除いて、クライアント側ルーティング(Linkrouter.push)には適用されません。

リダイレクトが適用されると、リクエストで提供されたクエリ値はすべてリダイレクト先に渡されます。たとえば、以下のリダイレクト設定を見てください:

{
source: '/old-blog/:path*',
destination: '/blog/:path*',
permanent: false
}

/old-blog/post-1?hello=worldがリクエストされると、クライアントは/blog/post-1?hello=worldにリダイレクトされます。

パスマッチング

パスマッチングは許可されています。例えば、/old-blog/:slug/old-blog/hello-world(ネストされたパスなし)と一致します:

next.config.js
module.exports = {
async redirects() {
return [
{
source: '/old-blog/:slug',
destination: '/news/:slug', // マッチしたパラメータを宛先で使用できます
permanent: true,
},
]
},
}

ワイルドカードパスマッチング

ワイルドカードパスと一致させるには、パラメータの後に*を使用できます。たとえば、/blog/:slug*/blog/a/b/c/d/hello-worldと一致します:

next.config.js
module.exports = {
async redirects() {
return [
{
source: '/blog/:slug*',
destination: '/news/:slug*', // マッチしたパラメータを宛先で使用できます
permanent: true,
},
]
},
}

正規表現パスマッチング

正規表現パスと一致させるには、パラメータの後に正規表現を括弧で囲んでください。たとえば、/post/:slug(\\d{1,})/post/123と一致しますが、/post/abcとは一致しません:

next.config.js
module.exports = {
async redirects() {
return [
{
source: '/post/:slug(\\d{1,})',
destination: '/news/:slug', // マッチしたパラメータを宛先で使用できます
permanent: false,
},
]
},
}

次の文字 (, ), {, }, :, *, +, ?は正規表現パスマッチングに使用されるため、それらをsourceで非特殊値として使用する場合は、先頭に\\を追加してエスケープする必要があります:

next.config.js
module.exports = {
async redirects() {
return [
{
// これは`/english(default)/something`がリクエストされると一致します
source: '/english\\(default\\)/:slug',
destination: '/en-us/:slug',
permanent: false,
},
]
},
}

リダイレクトをヘッダー、Cookie、またはクエリ値がhasフィールドに一致する場合、あるいはmissingフィールドに一致しない場合にのみ適用させるには、これらのフィールドが使用できます。リダイレクトが適用されるためには、sourceおよびすべてのhasアイテムが一致し、すべてのmissingアイテムが一致しない必要があります。

hasおよびmissingアイテムは次のフィールドを持つことができます:

  • type: String - headercookiehost、またはqueryのいずれかである必要があります。
  • key: String - 選択されたタイプから一致させるキー。
  • value: Stringまたはundefined - チェックする値。未定義の場合、任意の値が一致します。特定の部分をキャプチャするために、正規表現に似た文字列を使用できます。たとえば、値first-(?<paramName>.*)first-secondに使用される場合、second:paramNameで宛先で使用可能です。
next.config.js
module.exports = {
async redirects() {
return [
// ヘッダー `x-redirect-me` が存在する場合、
// このリダイレクトが適用されます
{
source: '/:path((?!another-page$).*)',
has: [
{
type: 'header',
key: 'x-redirect-me',
},
],
permanent: false,
destination: '/another-page',
},
// ヘッダー `x-dont-redirect` が存在する場合、
// このリダイレクトは適用されません
{
source: '/:path((?!another-page$).*)',
missing: [
{
type: 'header',
key: 'x-do-not-redirect',
},
],
permanent: false,
destination: '/another-page',
},
// ソース、クエリ、Cookieが一致する場合、
// このリダイレクトが適用されます
{
source: '/specific/:path*',
has: [
{
type: 'query',
key: 'page',
// ページの値は宛先で利用できません
// なぜなら値が提供されており、名前付きのキャプチャグループ
// (例:(?<page>home))を使用していないからです
value: 'home',
},
{
type: 'cookie',
key: 'authorized',
value: 'true',
},
],
permanent: false,
destination: '/another/:path*',
},
// ヘッダー `x-authorized` が存在し、
// 一致する値を含む場合、このリダイレクトが適用されます
{
source: '/',
has: [
{
type: 'header',
key: 'x-authorized',
value: '(?<authorized>yes|true)',
},
],
permanent: false,
destination: '/home?authorized=:authorized',
},
// ホストが `example.com` の場合、
// このリダイレクトが適用されます
{
source: '/:path((?!another-page$).*)',
has: [
{
type: 'host',
value: 'example.com',
},
],
permanent: false,
destination: '/another-page',
},
]
},
}

basePath サポートがあるリダイレクト

リダイレクトでbasePathサポートを活用する場合、拡張設定なしで、各sourceおよびdestinationは自動的にbasePathで接頭辞が付けられます。リダイレクトにbasePath: falseが追加されている場合を除きます:

next.config.js
module.exports = {
basePath: '/docs',

async redirects() {
return [
{
source: '/with-basePath', // 自動的に /docs/with-basePath になります
destination: '/another', // 自動的に /docs/another になります
permanent: false,
},
{
// basePath: false が設定されているため /docs は追加されません
source: '/without-basePath',
destination: 'https://example.com',
basePath: false,
permanent: false,
},
]
},
}

i18nサポートがあるリダイレクト

リダイレクトでi18nサポートを活用する際、各sourceおよびdestinationは、構成されたlocalesを処理するために自動的にプレフィックスが付けられます。リダイレクトにlocale: falseが追加されている場合を除きます。locale: falseが使用されている場合、正しく一致させるためにsourceおよびdestinationにロケールでプレフィックスを追加する必要があります。

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

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

珍しいケースですが、一部の古いHTTPクライアントが適切にリダイレクトを行うためにカスタムステータスコードを割り当てる必要があるかもしれません。これらの場合、permanentプロパティではなくstatusCodeプロパティを使用できますが、両方を使用することはできません。IE11との互換性を確保するため、308ステータスコードには自動的にRefreshヘッダーが追加されます。

その他のリダイレクト

バージョン履歴

バージョン変更
v13.3.0missingを追加
v10.2.0hasを追加
v9.5.0redirectsを追加