コンテンツへスキップ

redirects

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

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

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

redirectsは、sourcedestinationpermanentプロパティを持つオブジェクトの配列が返されることを期待する非同期関数です。

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

Next.jsが307と308を使用する理由は何ですか? 従来、一時的なリダイレクトには302が使用され、永続的なリダイレクトには301が使用されていましたが、多くのブラウザは、元のメソッドに関係なく、リダイレクトのリクエストメソッドをGETに変更しました。たとえば、ブラウザがPOST /v1/usersにリクエストを行い、ロケーション/v2/usersとともにステータスコード302を返した場合、その後のリクエストは期待されるPOST /v2/usersではなく、GET /v2/usersになる可能性があります。Next.jsは、使用されたリクエストメソッドを明示的に保持するために、307の一時的なリダイレクトと308の永続的なリダイレクトステータスコードを使用します。

  • basePath: falseまたはundefined - falseの場合、マッチング時にbasePathは含まれません。外部リダイレクトでのみ使用できます。
  • locale: falseまたはundefined - マッチング時にロケールを含めるべきかどうかを示します。
  • hasは、typekey、およびvalueプロパティを持つhasオブジェクトの配列です。
  • missingは、typekey、およびvalueプロパティを持つmissingオブジェクトの配列です。

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

Pages Routerを使用している場合、Middlewareが存在しパスと一致しない限り、クライアントサイドルーティング (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にマッチします(ネストされたパスはなし)。

next.config.js
module.exports = {
  async redirects() {
    return [
      {
        source: '/old-blog/:slug',
        destination: '/news/:slug', // Matched parameters can be used in the destination
        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*', // Matched parameters can be used in the destination
        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', // Matched parameters can be used in the destination
        permanent: false,
      },
    ]
  },
}

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

next.config.js
module.exports = {
  async redirects() {
    return [
      {
        // this will match `/english(default)/something` being requested
        source: '/english\\(default\\)/:slug',
        destination: '/en-us/:slug',
        permanent: false,
      },
    ]
  },
}

ヘッダー、Cookie、またはクエリの値がhasフィールドと一致する場合、またはmissingフィールドと一致しない場合にのみリダイレクトを適用するには、hasフィールドまたはmissingフィールドを使用できます。リダイレクトが適用されるには、sourceとすべてのhas項目が一致し、すべてのmissing項目が一致しない必要があります。

hasmissing項目は以下のフィールドを持つことができます。

  • type: String - headercookiehost、またはqueryのいずれかである必要があります。
  • key: String - 選択されたタイプからマッチングするキー。
  • value: Stringまたはundefined - チェックする値。undefinedの場合、任意の値がマッチします。値の特定の部分をキャプチャするために正規表現のような文字列を使用できます。例えば、first-(?<paramName>.*)first-secondに使用された場合、secondは宛先で:paramNameとして使用できます。
next.config.js
module.exports = {
  async redirects() {
    return [
      // if the header `x-redirect-me` is present,
      // this redirect will be applied
      {
        source: '/:path((?!another-page$).*)',
        has: [
          {
            type: 'header',
            key: 'x-redirect-me',
          },
        ],
        permanent: false,
        destination: '/another-page',
      },
      // if the header `x-dont-redirect` is present,
      // this redirect will NOT be applied
      {
        source: '/:path((?!another-page$).*)',
        missing: [
          {
            type: 'header',
            key: 'x-do-not-redirect',
          },
        ],
        permanent: false,
        destination: '/another-page',
      },
      // if the source, query, and cookie are matched,
      // this redirect 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',
          },
        ],
        permanent: false,
        destination: '/another/:path*',
      },
      // if the header `x-authorized` is present and
      // contains a matching value, this redirect will be applied
      {
        source: '/',
        has: [
          {
            type: 'header',
            key: 'x-authorized',
            value: '(?<authorized>yes|true)',
          },
        ],
        permanent: false,
        destination: '/home?authorized=:authorized',
      },
      // if the host is `example.com`,
      // this redirect will be applied
      {
        source: '/:path((?!another-page$).*)',
        has: [
          {
            type: 'host',
            value: 'example.com',
          },
        ],
        permanent: false,
        destination: '/another-page',
      },
    ]
  },
}

basePathサポート付きのリダイレクト

リダイレクトでbasePathサポートを利用する場合、リダイレクトにbasePath: falseを追加しない限り、各sourcedestinationは自動的にbasePathでプレフィックスされます。

next.config.js
module.exports = {
  basePath: '/docs',
 
  async redirects() {
    return [
      {
        source: '/with-basePath', // automatically becomes /docs/with-basePath
        destination: '/another', // automatically becomes /docs/another
        permanent: false,
      },
      {
        // does not add /docs since basePath: false is set
        source: '/without-basePath',
        destination: 'https://example.com',
        basePath: false,
        permanent: false,
      },
    ]
  },
}

i18nサポート付きのリダイレクト

リダイレクトでi18nサポートを利用する場合、リダイレクトにlocale: falseを追加しない限り、各sourcedestinationは設定されたlocalesを処理するために自動的にプレフィックスされます。locale: falseを使用する場合、正しくマッチングされるためには、sourcedestinationにロケールをプレフィックスする必要があります。

next.config.js
module.exports = {
  i18n: {
    locales: ['en', 'fr', 'de'],
    defaultLocale: 'en',
  },
 
  async redirects() {
    return [
      {
        source: '/with-locale', // automatically handles all locales
        destination: '/another', // automatically passes the locale on
        permanent: false,
      },
      {
        // does not handle locales automatically since locale: false is set
        source: '/nl/with-locale-manual',
        destination: '/nl/another',
        locale: false,
        permanent: false,
      },
      {
        // this matches '/' since `en` is the defaultLocale
        source: '/en',
        destination: '/en/another',
        locale: false,
        permanent: false,
      },
      // it's possible to match all locales even when locale: false is set
      {
        source: '/:locale/page',
        destination: '/en/newpage',
        permanent: false,
        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',
        permanent: false,
      },
    ]
  },
}

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

その他のリダイレクト

バージョン履歴

バージョン変更点
v13.3.0missingが追加されました。
v10.2.0hasが追加されました。
v9.5.0redirectsが追加されました。