重定向规则 #

什么是重定向? #

重定向是将一个 URL 指向另一个 URL 的机制。

text
用户访问 /old → 重定向到 /new

重定向类型 #

类型 状态码 说明
永久重定向 301 搜索引擎会更新索引
临时重定向 302 搜索引擎保留原 URL
重写 200 URL 不变,内容来自其他路径

配置方式 #

方式一:netlify.toml #

toml
[[redirects]]
  from = "/old"
  to = "/new"
  status = 301

方式二:_redirects 文件 #

text
# static/_redirects
/old    /new    301

优先级 #

text
netlify.toml > _redirects 文件

基本重定向 #

简单重定向 #

toml
[[redirects]]
  from = "/old-page"
  to = "/new-page"
  status = 301

重定向到外部 URL #

toml
[[redirects]]
  from = "/blog"
  to = "https://blog.example.com"
  status = 301

强制 HTTPS #

toml
[[redirects]]
  from = "http://example.com/*"
  to = "https://example.com/:splat"
  status = 301
  force = true

通配符 #

基本通配符 #

toml
[[redirects]]
  from = "/posts/*"
  to = "/articles/:splat"
  status = 301

:splat 匹配 * 的内容:

text
/posts/hello  → /articles/hello
/posts/world  → /articles/world

多个通配符 #

toml
[[redirects]]
  from = "/*/*/post"
  to = "/posts/:splat"
  status = 301

占位符 #

命名占位符 #

toml
[[redirects]]
  from = "/posts/:year/:month/:slug"
  to = "/blog/:slug?year=:year&month=:month"
  status = 302

示例:

text
/posts/2024/01/hello → /blog/hello?year=2024&month=01

可选占位符 #

toml
[[redirects]]
  from = "/posts/:slug?"
  to = "/blog/:slug"
  status = 301

查询参数 #

匹配查询参数 #

toml
[[redirects]]
  from = "/search"
  to = "/search-results?q=:q"
  status = 302
  query = {q = ":q"}

多个查询参数 #

toml
[[redirects]]
  from = "/products"
  to = "/shop?category=:cat&sort=:sort"
  query = {cat = ":cat", sort = ":sort"}

URL 重写 #

基本重写 #

toml
[[redirects]]
  from = "/api/*"
  to = "/.netlify/functions/:splat"
  status = 200

状态码 200 表示重写,URL 不变。

SPA 路由支持 #

toml
[[redirects]]
  from = "/*"
  to = "/index.html"
  status = 200

所有路由都返回 index.html,由前端处理路由。

代理 API #

toml
[[redirects]]
  from = "/api/*"
  to = "https://api.example.com/:splat"
  status = 200

条件重定向 #

按语言重定向 #

toml
[[redirects]]
  from = "/"
  to = "/en/"
  status = 302
  conditions = {Language = ["en"]}

[[redirects]]
  from = "/"
  to = "/zh/"
  status = 302
  conditions = {Language = ["zh", "zh-CN", "zh-TW"]}

按国家重定向 #

toml
[[redirects]]
  from = "/"
  to = "/us/"
  status = 302
  conditions = {Country = ["US", "CA"]}

[[redirects]]
  from = "/"
  to = "/cn/"
  status = 302
  conditions = {Country = ["CN"]}

按角色重定向 #

toml
[[redirects]]
  from = "/admin"
  to = "/login"
  status = 302
  conditions = {Role = ["admin"]}

按用户代理重定向 #

toml
[[redirects]]
  from = "/download"
  to = "/download/ios"
  status = 302
  conditions = {UserAgent = ["iPhone", "iPad"]}

[[redirects]]
  from = "/download"
  to = "/download/android"
  status = 302
  conditions = {UserAgent = ["Android"]}

Signed Redirects #

什么是 Signed Redirects? #

使用签名令牌验证重定向请求。

配置 #

toml
[[redirects]]
  from = "/protected/*"
  to = "https://cdn.example.com/:splat"
  status = 302
  signed = "API_SIGNING_KEY"

生成签名 URL #

javascript
const crypto = require('crypto')

function generateSignedUrl(path, key) {
  const expiry = Math.floor(Date.now() / 1000) + 3600 // 1小时后过期
  const stringToSign = `${path}?expiry=${expiry}`
  const signature = crypto
    .createHmac('sha256', key)
    .update(stringToSign)
    .digest('hex')
  
  return `${path}?expiry=${expiry}&signature=${signature}`
}

重定向优先级 #

规则顺序 #

规则按定义顺序匹配,先匹配的优先生效:

toml
# 这个规则先匹配
[[redirects]]
  from = "/posts/hello"
  to = "/articles/hello"
  status = 301

# 这个规则不会匹配 /posts/hello
[[redirects]]
  from = "/posts/*"
  to = "/blog/:splat"
  status = 301

最佳实践 #

将具体规则放在前面,通配规则放在后面:

toml
# 具体规则
[[redirects]]
  from = "/posts/hello"
  to = "/articles/hello"
  status = 301

# 通配规则
[[redirects]]
  from = "/posts/*"
  to = "/blog/:splat"
  status = 301

# 默认规则(SPA)
[[redirects]]
  from = "/*"
  to = "/index.html"
  status = 200

常见场景 #

场景1:网站迁移 #

toml
# 旧博客文章重定向
[[redirects]]
  from = "/blog/:year/:month/:slug"
  to = "/posts/:slug"
  status = 301

# 旧分类页面重定向
[[redirects]]
  from = "/category/:name"
  to = "/topics/:name"
  status = 301

场景2:API 代理 #

toml
# 代理到 Serverless Functions
[[redirects]]
  from = "/api/*"
  to = "/.netlify/functions/:splat"
  status = 200

# 代理到外部 API
[[redirects]]
  from = "/external-api/*"
  to = "https://api.example.com/:splat"
  status = 200

场景3:多语言站点 #

toml
# 默认语言
[[redirects]]
  from = "/"
  to = "/en/"
  status = 302

# 中文用户
[[redirects]]
  from = "/"
  to = "/zh/"
  status = 302
  conditions = {Language = ["zh"]}

# 日文用户
[[redirects]]
  from = "/"
  to = "/ja/"
  status = 302
  conditions = {Language = ["ja"]}

场景4:维护模式 #

toml
[[redirects]]
  from = "/*"
  to = "/maintenance.html"
  status = 503
  force = true

场景5:移除尾部斜杠 #

toml
[[redirects]]
  from = "/*/"
  to = "/:splat"
  status = 301

调试重定向 #

查看重定向规则 #

bash
netlify deploy --prod

部署后会显示重定向规则数量。

测试重定向 #

bash
curl -I https://your-site.netlify.app/old-page

查看响应头中的 Location 字段。

常见问题 #

问题1:重定向不生效

检查:

  • 规则语法是否正确
  • 规则顺序是否合理
  • 是否需要重新部署

问题2:重定向循环

检查:

  • 是否有相互重定向的规则
  • force 参数是否正确使用

问题3:SPA 路由 404

确保添加了 SPA 重定向规则:

toml
[[redirects]]
  from = "/*"
  to = "/index.html"
  status = 200

_redirects 文件语法 #

基本语法 #

text
# 注释
/from    /to    status

# 示例
/home    /       301
/blog    /posts  301

通配符 #

text
/posts/*    /articles/:splat    301

查询参数 #

text
/search    /search-results    302    q=:q

条件 #

text
/    /en/    302    Language=en
/    /zh/    302    Language=zh

最佳实践 #

1. 使用 301 还是 302? #

  • 永久移动:使用 301
  • 临时移动:使用 302

2. 保持 URL 简洁 #

toml
# 好的做法
[[redirects]]
  from = "/about"
  to = "/about-us"
  status = 301

# 不好的做法(复杂路径)
[[redirects]]
  from = "/pages/about/company/info"
  to = "/about"
  status = 301

3. 避免重定向链 #

text
不好:A → B → C
好:A → C

4. 测试重定向 #

部署后测试所有重定向规则是否正常工作。

下一步 #

掌握了重定向规则后,继续学习 自定义 Headers 了解 HTTP 头配置!

最后更新:2026-03-28