redirects
リダイレクトを使用すると、受け取ったリクエストパスを別の宛先パスにリダイレクトできます。
リダイレクトを使用するには、next.config.jsでredirectsキーを使用できます:
module.exports = {
async redirects() {
return [
{
source: '/about',
destination: '/',
permanent: true,
},
]
},
}redirectsは非同期関数で、source、destination、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永続的リダイレクトステータスコードを使用して、使用されたリクエストメソッドを明示的に保持します。
basePath:falseまたはundefined- falseの場合、マッチング時にbasePathは含まれません。外部リダイレクトにのみ使用できます。locale:falseまたはundefined- マッチング時にロケールを含めるかどうか。hasはtype、key、valueプロパティを持つhasオブジェクトの配列です。missingはtype、key、valueプロパティを持つmissingオブジェクトの配列です。
リダイレクトはページと/publicファイルを含むファイルシステムの前にチェックされます。
ページルーターを使用する場合、Proxyが存在してパスに一致しない限り、リダイレクトはクライアント側ルーティング(Link、router.push)に適用されません。
リダイレクトが適用されると、リクエストで提供されたクエリ値はすべてリダイレクト先に渡されます。例えば、次のリダイレクト設定を参照してください:
{
source: '/old-blog/:path*',
destination: '/blog/:path*',
permanent: false
}補足:
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', // マッチしたパラメータをdestinationで使用できます
permanent: true,
},
]
},
}ワイルドカードパスマッチング
ワイルドカードパスをマッチさせるには、パラメータの後に*を使用できます。例えば/blog/:slug*は/blog/a/b/c/d/hello-worldにマッチします:
module.exports = {
async redirects() {
return [
{
source: '/blog/:slug*',
destination: '/news/:slug*', // マッチしたパラメータをdestinationで使用できます
permanent: true,
},
]
},
}正規表現パスマッチング
正規表現パスをマッチさせるには、パラメータの後に正規表現を括弧で囲むことができます。例えば/post/:slug(\\d{1,})は/post/123にマッチしますが/post/abcにはマッチしません:
module.exports = {
async redirects() {
return [
{
source: '/post/:slug(\\d{1,})',
destination: '/news/:slug', // マッチしたパラメータをdestinationで使用できます
permanent: false,
},
]
},
}以下の文字(、)、{、}、:、*、+、?は正規表現パスマッチングに使用されるため、sourceで特殊値以外として使用する場合は、それらの前に\\を追加してエスケープする必要があります:
module.exports = {
async redirects() {
return [
{
// これは`/english(default)/something`がリクエストされた場合にマッチします
source: '/english\\(default\\)/:slug',
destination: '/en-us/:slug',
permanent: false,
},
]
},
}ヘッダー、クッキー、クエリマッチング
ヘッダー、クッキー、またはクエリ値がマッチする場合のみリダイレクトをマッチさせるには、hasフィールドを使用するか、missingフィールドを使用してマッチしない場合を指定できます。sourceと全てのhasアイテムがマッチし、全てのmissingアイテムがマッチしない場合、リダイレクトが適用されます。
hasとmissingアイテムは以下のフィールドを持つことができます:
type:String-header、cookie、host、またはqueryのいずれかである必要があります。key:String- マッチ対象の選択されたタイプからのキー。value:Stringまたはundefined- チェックする値。undefinedの場合、任意の値がマッチします。値の特定の部分をキャプチャするために正規表現のような文字列を使用できます。例えば、値first-(?<paramName>.*)がfirst-secondに使用される場合、secondはdestinationで: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、クエリ、クッキーがマッチする場合、
// このリダイレクトが適用されます
{
source: '/specific/:path*',
has: [
{
type: 'query',
key: 'page',
// value が提供されており、名前付きキャプチャグループを
// 使用していないため、page値はdestinationで利用できません
// 例:(?<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: falseを追加しない限り、自動的にbasePathが接頭辞として付けられます:
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サポート付きリダイレクト
App Routerで国際化を実装するリダイレクトを使用する場合、next.config.jsリダイレクトにロケールを含めることができますが、ハードコードされたパスのみです。
動的またはリクエストごとのロケール処理の場合、動的ルートセグメントとプロキシを使用してください。これはユーザーの優先言語に基づいてリダイレクトできます。
module.exports = {
async redirects() {
return [
{
// App Router のロケールプレフィックスを手動で処理
source: '/en/old-path',
destination: '/en/new-path',
permanent: false,
},
{
// パラメータを使用してすべてのロケールをリダイレクト
source: '/:locale/old-path',
destination: '/:locale/new-path',
permanent: false,
},
{
// あるロケールから別のロケールへリダイレクト
source: '/de/old-path',
destination: '/en/new-path',
permanent: false,
},
{
// 複数のロケールのキャッチオールリダイレクト
source: '/:locale(en|fr|de)/:path*',
destination: '/:locale/new-section/:path*',
permanent: false,
},
]
},
}まれな場合として、古いHTTPクライアントが正しくリダイレクトするようにカスタムステータスコードを割り当てる必要があることがあります。このような場合、permanentプロパティの代わりにstatusCodeプロパティを使用できますが、両方は使用できません。IE11との互換性を確保するために、308ステータスコードに対してRefreshヘッダーが自動的に追加されます。
その他のリダイレクト
- APIルートおよびルートハンドラー内で、受け取ったリクエストに基づいてリダイレクトできます。
getStaticPropsおよびgetServerSideProps内で、リクエスト時に特定のページをリダイレクトできます。
バージョン履歴
| バージョン | 変更内容 |
|---|---|
v13.3.0 | missingが追加されました。 |
v10.2.0 | hasが追加されました。 |
v9.5.0 | redirectsが追加されました。 |