Blitz 尚在 beat 阶段! 🎉 预计会在今年的 Q3 季度发布 1.0
Back to Documentation Menu

重定向

Topics

Jump to a Topic

重定向允许你重定向一个到来的请求路径到一个不同的目标路径。

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

在客户端上

一个常见的用例是根据用户的会话数据有条件地将用户重定向到不同的页面。你可以 这样做:

import { useRouter, useSession } from "blitz"

const LoginPage: BlitzPage = () => {
  const router = useRouter()
  const session = useSession()

  useEffect(() => {
    if (session.userId) {
      router.push("/home")
    }
  })

  return /* 填充 */
}

在服务端上

如果你不想让客户端重定向出现“无效内容闪现”现象,你可以使用 getServerSideProps 有条件地从服务器重定向。你 可以这样做:

import { getSession } from "blitz"

export const getServerSideProps = async ({ req, res }) => {
  const session = await getSession(req, res)

  if (!session.userId) {
    return {
      redirect: {
        destination: "/login",
        permanent: false,
      },
    }
  }

  return { props: {} }
}

全局重定向

要使用全局重定向,你可以使用 blitz.config.js 中的 redirects 键:

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

redirects 是一个异步函数,它期望返回一个具有 sourcedestinationpermanent 属性的对象的数组:

  • source 是传入的请求路径模式。
  • destination 是你想要路由到的路径。
  • permanent 重定向是否是永久性的。
  • basePathfalseundefined——如果为 false,匹配时将不包含 basePath,只能用于外部重写。
  • localefalseundefined——匹配时是否不应该包含语言环境。
  • has 是具有 typekeyvalue 属性的 has 对象 数组。

在包含页面和 /public 文件的文件系统之前重定向将被检查。

路径匹配

允许路由匹配,例如 /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,
      },
    ]
  },
}

Header,Cookie 和查询匹配

要仅在 header、cookie 或查询值也匹配 has 字段时才匹配重定向并使用 。source 和所有 has 项都必须匹配才能使用重定向。

has 具有以下字段:

  • typeString——必须是 headercookiehostquery
  • keyString——所选类型中要匹配的键。
  • valueStringundefined——要检查的值,如果 undefined 将匹配任意 值。像字符串这样的正则表达式可用于捕获值的特定部分,例如如果值 first-(?<paramName>.*) 用于 first-second,那么 second 将在目的地中 使用 :paramName
module.exports = {
  async redirects() {
    return [
      // 如果 header 中有 `x-redirect-me` 存在,
      // 将使用此重定向
      {
        source: "/:path*",
        has: [
          {
            type: "header",
            key: "x-redirect-me",
          },
        ],
        permanent: false,
        destination: "/another-page",
      },
      // 如果源、查询和 cookie 匹配,
      // 将使用此重定向
      {
        source: "/specific/:path*",
        has: [
          {
            type: "query",
            key: "page",
            // 页面值在目标路径中将不可用,因为提供了值并且不适用命名的捕获组,
            // 例如(?<page>home)
            value: "home",
          },
          {
            type: "cookie",
            key: "authorized",
            value: "true",
          },
        ],
        permanent: false,
        destination: "/:path*/:page",
      },
      // 如果 header `x-authorized` 存在且包含一个匹配到的值,将使用此重定向
      {
        source: "/:path*",
        has: [
          {
            type: "header",
            key: "x-authorized",
            value: "(?<authorized>yes|true)",
          },
        ],
        permanent: false,
        destination: "/home?authorized=:authorized",
      },
      // 如果当前域名是 `example.com`,
      // 当前重定向将被使用
      {
        source: "/:path*",
        has: [
          {
            type: "host",
            value: "example.com",
          },
        ],
        destination: "/another-page",
      },
    ]
  },
}

使用 basePath 支持重定向

当利用 basePath 支持进行重定向时,每个 sourcedestination 都会自动以 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: "/another",
        basePath: false,
        permanent: false,
      },
    ]
  },
}

使用 i18n 支持重定向

当利用 i18n 支持 进行重定向时,每个 sourcedestination 都会自动添加前缀来处理配置的 locales,除非你向重定向添加 locale: false。如果使用 locale: false,你必须在 sourcedestination 前面加上一个区域设置,才能正确匹配。

module.exports = {
  i18n: {
    locales: ["en", "fr", "de"],
    defaultLocale: "en",
  },

  async redirects() {
    return [
      {
        source: "/with-locale", // 自动处理所有 locales
        destination: "/another", // 自动传递 locales
        permanent: false,
      },
      {
        // 自从 locale: false 被设置后,将不自动处理 locales
        source: "/nl/with-locale-manual",
        destination: "/nl/another",
        locale: false,
        permanent: false,
      },
      {
        // 自动 `en` 是 defaultLocale,将匹配 `/`
        source: "/en",
        destination: "/en/another",
        locale: false,
        permanent: false,
      },
      {
        // 这被转换为 /(en|fr|de)/(.*) 所以不会像 /:path*
        // 这样地匹配顶级 `/` 或 `/fr` 路由
        source: "/(.*)",
        destination: "/another",
        permanent: false,
      },
    ]
  },
}

在极少数情况下,你可能需要为较旧的 HTTP 客户端分配自定义状态代码以正确重定 向。在这种情况下,你可以使用 statusCode 属性代替 permanent 属性,但不 能同时使用两者。注意:为了确保 IE11 兼容性,会自动为 308 状态码添加一个 Refresh header。

其它重定向

  • API 路由中,你可以使用 res.redirect().

Idea for improving this page? Edit it on GitHub.