# 重定向

Examples

  • Redirects

Version History| Version | Changes | | :--- | :--- | | v10.2.0| has added. | | v9.5.0| Redirects added. |

重定向允许您将传入请求路径重定向到不同的目标路径。

重定向只在Node.js环境中可用,不影响客户端路由。

To use Redirects you can use the redirectskey in next.config.js:

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

redirectsis an async function that expects an array to be returned holding objects with source, destination, and permanentproperties:

  • sourceis the incoming request path pattern.
  • destinationis the path you want to route to.
  • permanent``trueor false- if truewill use the 308 status code which instructs clients/search engines to cache the redirect forever, if falsewill use the 307 status code which is temporary and is not cached.
  • basePath: falseor undefined- if false the basePath won't be included when matching, can be used for external rewrites only.
  • locale: falseor undefined- whether the locale should not be included when matching.
  • hasis an array of has objects with the type, keyand valueproperties.

Redirects are checked before the filesystem which includes pages and /publicfiles.

When a redirect is applied, any query values provided in the request will be passed through to the redirect destination. For example, see the following redirect configuration:

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

When /old-blog/post-1?hello=worldis requested, the client will be redirected to /blog/post-1?hello=world.

# Path Matching

Path matches are allowed, for example /old-blog/:slugwill match /old-blog/hello-world(no nested paths):

module.exports = {
  async redirects() {
    return [
      {
        source: '/old-blog/:slug',
        destination: '/news/:slug', // Matched parameters can be used in the destination
        permanent: true,
      },
    ]
  },
}

# Wildcard Path Matching

To match a wildcard path you can use *after a parameter, for example /blog/:slug*will match /blog/a/b/c/d/hello-world:

module.exports = {
  async redirects() {
    return [
      {
        source: '/blog/:slug*',
        destination: '/news/:slug*', // Matched parameters can be used in the destination
        permanent: true,
      },
    ]
  },
}

# Regex Path Matching

To match a regex path you can wrap the regex in parentheses after a parameter, for example /post/:slug(\\d{1,})will match /post/123but not /post/abc:

module.exports = {
  async redirects() {
    return [
      {
        source: '/post/:slug(\\d{1,})',
        destination: '/news/:slug', // Matched parameters can be used in the destination
        permanent: false,
      },
    ]
  },
}

The following characters (, ), {, }, :, *, +, ?are used for regex path matching, so when used in the sourceas non-special values they must be escaped by adding \\before them:

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

To only match a redirect when header, cookie, or query values also match the hasfield can be used. Both the sourceand all hasitems must match for the redirect to be applied.

hasitems have the following fields:

  • type: String- must be either header, cookie, host, or query.
  • key: String- the key from the selected type to match against.
  • value: Stringor undefined- the value to check for, if undefined any value will match. A regex like string can be used to capture a specific part of the value, e.g. if the value first-(?<paramName>.*)is used for first-secondthen secondwill be usable in the destination with :paramName.
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 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',
      },
    ]
  },
}

# Redirects with basePath support

When leveraging basePath support with redirects each sourceand destinationis automatically prefixed with the basePathunless you add basePath: falseto the redirect:

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: '/another',
        basePath: false,
        permanent: false,
      },
    ]
  },
}

# Redirects with i18n support

When leveraging i18n support with redirects each sourceand destinationis automatically prefixed to handle the configured localesunless you add locale: falseto the redirect. If locale: falseis used you must prefix the sourceand destinationwith a locale for it to be matched correctly.

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

In some rare cases, you might need to assign a custom status code for older HTTP Clients to properly redirect. In these cases, you can use the statusCodeproperty instead of the permanentproperty, but not both. Note: to ensure IE11 compatibility a Refreshheader is automatically added for the 308 status code.

# Other Redirects

  • Inside API Routes , you can use res.redirect().
  • Inside getStaticProps and getServerSideProps , you can redirect specific pages at request-time.
Last Updated: 5/13/2023, 8:55:38 PM