redirects
リダイレクトを使用すると、受信リクエストのパスを別の宛先パスにリダイレクトできます。
リダイレクトを使用するには、next.config.jsでredirectsキーを使用します:
module.exports = {
async redirects() {
return [
{
source: '/about',
destination: '/',
permanent: true,
},
]
},
}
redirectsは非同期関数で、source、destination、permanentプロパティを持つオブジェクトを含む配列を返すことを期待します:
sourceは受信リクエストのパスパターンですdestinationはルーティングしたいパスですpermanentはtrueまたは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永続リダイレクトステータスコードを使用します。
basePath:falseまたはundefined- falseの場合、basePathはマッチング時に含まれず、外部リダイレクトにのみ使用できますlocale:falseまたはundefined- ロケールがマッチング時に含まれないかどうかhasはtype、key、valueプロパティを持つhasオブジェクトの配列ですmissingはtype、key、valueプロパティを持つmissingオブジェクトの配列です
リダイレクトは、ページや/publicファイルを含むファイルシステムの前にチェックされます。
Pages Routerを使用する場合、Middlewareが存在し、パスに一致しない限り、クライアントサイドのルーティング(Link、router.push)にはリダイレクトは適用されません。
リダイレクトが適用されると、リクエストで提供されたクエリ値はリダイレクト先に渡されます。たとえば、次のリダイレクト設定を参照してください:
{
source: '/old-blog/:path*',
destination: '/blog/:path*',
permanent: false
}
Good to know:
sourceとdestinationパスのパスパラメータにコロン:の前にスラッシュ/を含めることを忘れないでください。そうしないと、パスがリテラル文字列として扱われ、無限リダイレクトを引き起こすリスクがあります。
/old-blog/post-1?hello=worldがリクエストされると、クライアントは/blog/post-1?hello=worldにリダイレクトされます。
パスマッチング
パスマッチングが許可されています。たとえば、/old-blog/:slugは/old-blog/hello-world(ネストされたパスなし)にマッチします:
module.exports = {
async redirects() {
return [
{
source: '/old-blog/:slug',
destination: '/news/:slug', // マッチしたパラメータは宛先で使用できます
permanent: true,
},
]
},
}
ワイルドカードパスマッチング
ワイルドカードパスにマッチさせるには、パラメータの後に*を使用します。たとえば、/blog/:slug*は/blog/a/b/c/d/hello-worldにマッチします:
module.exports = {
async redirects() {
return [
{
source: '/blog/:slug*',
destination: '/news/:slug*', // マッチしたパラメータは宛先で使用できます
permanent: true,
},
]
},
}
正規表現パスマッチング
正規表現パスにマッチさせるには、パラメータの後に括弧で正規表現を囲みます。たとえば、/post/:slug(\\d{1,})は/post/123にマッチしますが、/post/abcにはマッチしません:
module.exports = {
async redirects() {
return [
{
source: '/post/:slug(\\d{1,})',
destination: '/news/:slug', // マッチしたパラメータは宛先で使用できます
permanent: false,
},
]
},
}
次の文字(、)、{、}、:、*、+、?は正規表現パスマッチングに使用されるため、sourceで非特殊値として使用する場合は、前に\\を追加してエスケープする必要があります:
module.exports = {
async redirects() {
return [
{
// これは`/english(default)/something`がリクエストされるとマッチします
source: '/english\\(default\\)/:slug',
destination: '/en-us/:slug',
permanent: false,
},
]
},
}
ヘッダー、Cookie、およびクエリのマッチング
ヘッダー、Cookie、またはクエリの値がhasフィールドに一致する場合、またはmissingフィールドに一致しない場合にのみリダイレクトをマッチさせることができます。リダイレクトが適用されるためには、sourceとすべてのhasアイテムが一致し、すべてのmissingアイテムが一致しない必要があります。
hasとmissingアイテムには次のフィールドがあります:
type:String-header、cookie、host、またはqueryのいずれかである必要がありますkey:String- 一致させるために選択されたタイプのキーvalue:Stringまたはundefined- チェックする値。未定義の場合、任意の値が一致します。特定の部分をキャプチャするために正規表現のような文字列を使用できます。たとえば、値first-(?<paramName>.*)がfirst-secondに使用される場合、secondは宛先で:paramNameとして使用できます。
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',
},
// source、query、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を追加した場合は除きます:
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にロケールをプレフィックスする必要があります。
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ヘッダーが追加されます。
その他のリダイレクト
- API RoutesとRoute Handlersの内部で、受信リクエストに基づいてリダイレクトできます
getStaticPropsとgetServerSidePropsの内部で、リクエスト時に特定のページをリダイレクトできます
バージョン履歴
| バージョン | 変更点 |
|---|---|
v13.3.0 | missingが追加されました |
v10.2.0 | hasが追加されました |
v9.5.0 | redirectsが追加されました |