🚀

【Next.js和訳】API Reference/next.config.js/Redirects

8 min read

この記事について

株式会社 UnReact はプロジェクトの一環としてNext.js ドキュメントの和訳を行っています。

この記事は、next.config.js/Redirectsの記事を和訳したものです。

記事内で使用する画像は、公式ドキュメント内の画像を引用して使用させていただいております。

リダイレクト

バージョン履歴
バージョン 変更点
v10.2.0 has が追加されました
v9.5.0 Redirects が追加されました

リダイレクトは、入力されたリクエストパスを別の宛先パスにリダイレクトすることができます。

リダイレクトは、Node.js 環境でのみ利用可能で、クライアントサイドのルーティングには影響しません。

Redirects を使用するには、next.config.jsredirectsキーを使用します。

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

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

  • source は、受信するリクエストのパスパターンです。
  • destination は、ルーティングしたいパスです。
  • permanent は、リダイレクトが永続的かどうかを表します。
  • basePath: falseまたはundefined - false の場合、マッチングの際に basePath が含まれません、外部の書き換えにのみ使用できます。
  • locale: false または undefined - マッチング時にロケールを含めないかどうかを指定します。
  • has は、typekeyvalueのプロパティを持つ has オブジェクトの配列です。

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

リダイレクトが適用されると、リクエストで指定されたクエリ値はすべてリダイレクト先に渡されます。例えば、次のようなリダイレクト設定を見てみましょう。

{
  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 にマッチします(ネストしたパスはありません)。

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(\\{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,
      },
    ]
  },
}

Header, Cookie, and Query Matching

Header, Cookie, Query の値が一致した場合にのみリダイレクトを適用するには、hasフィールドを使用します。リダイレクトが適用されるには、sourceとすべての has アイテムの両方が一致する必要があります。

has アイテムには、次のようなフィールドがあります。

  • type:String - headercookiehostqueryのいずれかでなければなりません。
  • key: String - 選択されたタイプのうち、照合するキーです。
  • value:Stringまたはundefinded - チェックする値で、未定義の場合はどんな値でもマッチします。例えば、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',
      },
       // ソース、クエリ、クッキーが一致した場合。
      // このリダイレクトが適用されます
      {
        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',
          },
        ],
        destination: '/another-page',
      },
    ]
  },
}

basePath サポートによるリダイレクト

basePathサポートを利用したリダイレクトでは、リダイレクトにbasePath: falseを追加しない限り、sourcedestinationのそれぞれに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: '/another',
        basePath: false。
        permanent: false},
    ]
  },
}

国際化対応のリダイレクト

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

module.exports = {
  i18n: {
    locales:['en', 'fr', 'de'],
    defaultLocale: 'en',
  },
  async redirects() {
    return [
      {
        source: '/with-locale', // すべてのロケールを自動的に処理します。
        destination: '/another', // 自動的にロケールを渡す
        permanent: false,
      },
      {
        // locale: false が設定されているため、ロケールを自動的に処理しない
        rource: '/nl/with-locale-manual',
        destination: '/nl/another',
        locale:false
        permanent: false},
      {
        // 「en」がデフォルトロケールであるため、「/」にマッチします。
        source: '/en',
        destination: '/en/another',
        locale: false,
        permanent: false,
      },
      {
        // これは/(en|fr|de)/(.*)に変換されるので、トップレベルにはマッチしません。
        // `/` や `/fr` のルートには /:path* のようにマッチしません。
        source: '/(.*)',
        destination: '/another',
        permanent: false,
      },
    ]
  },
}

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

その他のリダイレクト

Discussion

ログインするとコメントできます