你从 old.com 迁到 new.com。配了 old.com 到 new.com 的重定向,测了首页,通的。两周后 Search Console 显示新域名上数百个 404、流量下降、外链全打不开。
最快的修复:你几乎肯定只重定向了根,而不是每一条 URL 路径。只重定向根,会把 old.com/blog/article 跳到 new.com/(或一条已不存在的路径),于是 404。你需要的是一条保留路径的兜底规则,外加对那些结构变了的 URL 写显式规则,全部返回 301、全部部署在旧域名的托管上。跑一句 curl -sI "https://old.com/some-deep-url",看 Location: 响应头:如果它指向裸根或一条死路径,那就是你的 bug。
本文带你建一份完整的 redirect map,并在部署后验证。
你属于哪一类?
拿旧站一条真实的深 URL 跑一次 curl,看结果:
curl -sI https://old.com/blog/real-post 显示 | 诊断 | 跳到 |
|---|---|---|
301 + Location: https://new.com/(裸根) | 只重定向了根 | 原因 1 |
301 + Location: https://new.com/blog/real-post,但新站这页 404 | URL 结构改了,map 没跟上 | 原因 2 |
部分路径返回 200(根本没重定向) | 通配符/模式规则没匹配上 | 原因 3、4 |
https:// 请求报 TLS/证书错误 | 旧域名没有效证书 | 原因 6 |
Connection refused / 超时 | 旧托管彻底下线了 | 原因 5 |
常见原因
按命中率从高到低。
1. 只重定向了根,深 URL 没处理
old.com 到 new.com 只重定向了裸根。old.com/blog/article-name 跟随重定向,落到 new.com/(多数域名转发规则会丢掉路径),或落到可能不存在的 new.com/blog/article-name。两种都是 404。
怎么判断:
curl -sI "https://old.com/some-deep-url" | head -3
如果看到 Location: https://new.com/,就是只重定向了根。应该是 Location: https://new.com/some-deep-url。
2. URL 结构改了但 redirect map 没跟上
你在迁移时把 /blog/article-name 改成了 /articles/article-name。哪怕配了保留路径的完整重定向,请求还是落到新域名上的老路径,于是 404。
**怎么判断:**看重定向目标。如果它保留了老路径,但新站没有老路径,你就得在重定向里加一段路径改写(见下面 Vercel/Netlify 示例里对应原因 2 的那条规则)。
3. 通配符 / 模式重定向无效
你写了模式重定向,但平台不支持那个语法,于是静默回退成无重定向。三大静态托管的捕获语法各不相同:Vercel 用 :slug 和 :path*,Netlify 用 * 和 :splat,Firebase 用 :slug* 这种 glob 捕获。把一个平台的规则直接复制粘贴到另一个平台,是静默失败的常见原因。
怎么判断:curl 一条本该匹配该模式的 URL。返回 200(而不是 301)就说明模式从没匹配上。
4. 托管平台有重定向数量上限(截至 2026 年 6 月)
静态托管对一个配置文件能放多少条重定向规则有上限:
| 平台 | 文件 | 上限(2026 年 6 月) | 超出后怎么办 |
|---|---|---|---|
| Vercel | vercel.json 的 redirects | 1,024 条 | 用 Bulk Redirects(每项目最多 1,000,000 条)或 Edge Middleware |
| Vercel | 每次部署的总路由数 | 2,048 条路由 | 把静态重定向搬到 Edge Middleware / Bulk Redirects |
| Netlify | _redirects / netlify.toml | 无硬性条数上限;序列化输出过大则部署失败 | 多用通配符/占位符;超过约 10,000 条 Netlify 建议这么做;复杂场景用 Edge Functions |
| Firebase | firebase.json 的 redirects | 有实际 glob 规模上限 | 用 glob 捕获,别一条 URL 写一条规则 |
修法几乎从来不是”再加规则”,而是把成百上千条 1:1 规则收成几条通配符捕获加一条兜底。
**怎么判断:**数你配置里的规则条数。Vercel 上 vercel.json 超过 1,024 条的那部分会被丢掉。
5. 旧域名托管彻底下线了
如果你彻底关停了 old.com 的托管(不只是改 DNS),重定向就永远发不出去。旧 URL 返回连接拒绝或超时,Google 也没法跟随一个不响应的重定向。
怎么判断:curl -I https://old.com/anything 报网络错误。你需要保留一个只做重定向的部署。
6. HTTPS 旧域名没证书
你配了 HTTP 重定向,但对 old.com 的 HTTPS 请求在重定向发出之前就因证书错误失败了。现代浏览器默认 HTTPS,而任何曾经发过 HSTS 响应头的域名,在 max-age 窗口内都会强制 HTTPS,于是 HTTP 版本根本到不了。
怎么判断:curl -I https://old.com/ 报证书错误,而 curl -I http://old.com/ 通。重定向主机必须为旧域名提供有效证书(DNS 指向 Vercel、Netlify、Firebase 后它们都会自动签发一张)。
最短修复路径
第 1 步:导出所有旧 URL
来源,大致按完整度排序:
old.com/sitemap.xml(如果旧站或某个归档仍在提供)- Search Console(旧域名仍验证过)→ Performance → Pages → Export
- 旧托管的服务器访问日志(唯一能抓到那些 Google 从未收录、但用户仍在访问的 URL 的来源)
- Wayback Machine 找未收录页面
- 外链数据(Ahrefs、Majestic,或 Search Console 的 Links → Top linked pages)——这些正是你最需要保住链接权重的 URL
去重,合成一份路径清单。
第 2 步:建 redirect map
为每个旧 URL 决定目标:
- 有直接对应——直接映射:
old.com/blog/foo到new.com/articles/foo - 没精确对应——重定向到最近的分类:
old.com/topic-x/*到new.com/category/x/ - 真孤儿——只在万不得已时兜底到首页(首页重定向传递的链接权重远不如主题相关的目标,而且 Google 可能把大量”路径跳根”当成软 404)
用 CSV 把 map 保持可审查、可进版本控制:
old_path,new_path
/blog/article-name,/articles/article-name
/topics/ai,/category/ai
/old-broken-page,/
第 3 步:转成平台的 redirect 语法
具体规则在前,兜底在后——Vercel 和 Firebase 都按第一条匹配的规则执行,所以顺序重要。
Vercel — vercel.json(:slug 捕获一段,:path* 捕获剩余路径):
{
"redirects": [
{ "source": "/blog/:slug", "destination": "https://new.com/articles/:slug", "permanent": true },
{ "source": "/topics/:topic", "destination": "https://new.com/category/:topic", "permanent": true },
{ "source": "/:path*", "destination": "https://new.com/:path*", "permanent": true }
]
}
"permanent": true 发出的是 308(保留请求方法的现代永久重定向);对站点迁移而言,Google 把 301 和 308 同等对待。只有临时迁移才用 "permanent": false。
Netlify — _redirects(* 做匹配,:splat 是捕获到的尾段;若有真实文件可能盖住规则,用 301! 强制):
/blog/* https://new.com/articles/:splat 301!
/topics/* https://new.com/category/:splat 301!
/* https://new.com/:splat 301!
Firebase — firebase.json(glob 捕获用 :segment*):
{
"hosting": {
"redirects": [
{ "source": "/blog/:slug", "destination": "https://new.com/articles/:slug", "type": 301 },
{ "source": "/:path*", "destination": "https://new.com/:path*", "type": 301 }
]
}
}
第 4 步:把重定向部署在旧域名的托管上
这步是大多数人漏掉的。让 old.com 的托管继续跑,里面只有重定向规则——你不需要整个 app,只要一个极小的静态部署,它唯一的活就是承载这份重定向配置。Vercel、Netlify、Firebase 都能 host 一个除了 vercel.json / _redirects / firebase.json 之外什么都没有的”站点”。
然后在旧域名上确认两件事:
old.com(和www.old.com)的 DNS 仍指向这个重定向主机。- 重定向主机为旧域名持有有效 SSL 证书——否则会被原因 6 咬到。
第 5 步:用 curl 验证
随机抽 50+ 个旧 URL,确认每个都以永久重定向落到一个存在的新 URL:
while read -r url; do
# -L 跟随重定向,-o /dev/null 丢掉响应体,再打印最终状态码 + 重定向跳数
echo "$url -> $(curl -sIL -o /dev/null -w '%{http_code} via %{num_redirects} hop(s)' "$url")"
done < <(shuf old_urls.txt | head -50)
每行都应以 200 via 1 hop(s) 结尾(一次干净的 301/308 落到存在的页面)。要警惕:
... via 2 hop(s)或更多——重定向链(比如 http→https→新域名);把它压平,让旧 URL 一跳直达新 URL。- 最终
404——目标不存在;修 map 里那条。 - 非根 URL 却重定向到
https://new.com/——又是原因 1。
第 6 步:在 Search Console 提交 Change of Address
在旧域名的资源里:Settings → Change of address → Update,然后选新域名。截至 2026 年 6 月,该工具要求:
- 旧域名和新域名都在 Search Console 里、用同一个 Google 账号验证。
- 是域名级资源(
example.com,不是example.com/path)。 301已经在跑——工具会做迁移前检查,关键项不过就拦下来。
Google 现在建议对旧域名的每一个变体都跑一次 Change of Address——www 和非 www,以及任何子域名——哪怕你没在用。该工具会告诉 Google 把排名信号从旧资源迁到新资源。
第 7 步:重定向留得比你想的更久
Google 自己的指引(2026 年 6 月)是:重定向至少保留 180 天,只要旧 URL 还在收到 Search 流量就更久。实际中外链能存在好几年,所以那个只做重定向的部署无限期留着。别在迁移”感觉做完”后就撤掉。
怎么确认修好了
- 第 5 步的
curl循环里,每个抽到的 URL 都显示200 via 1 hop(s)。 - 在 Search Console(新域名)→ Indexing → Pages,“Not found (404)” 数量在几个抓取周期内停止攀升、随后下降。
- 在旧域名资源里,Change of Address 横幅显示为进行中/已完成的迁移,而不是 “not started”。
- 在浏览器里抽查 5 条权重最高的外链——每条都应落到正确的新域名页面,而不是 404。
容易误判的情况
有人以为 Google “自己会”。没有显式 301,链接权重就丢了。当 URL 结构变了,Google 不会去猜 old.com/foo 等于 new.com/foo——它需要重定向把两者连起来。一堆首页重定向也是个坑:Google 可能把”路径跳根”当软 404 丢弃,所以只要存在主题相关的对应页,就映射过去。
预防建议
- 在新域名上线前就建好 redirect map,别当成事后清理。
- 重定向规则进版本控制(
vercel.json、_redirects、firebase.json)。 - 旧域名的重定向部署无限期保留,永远别撤。
- 每次部署后,用上面那段
curl循环抽测 50+ 条重定向。 - 大站从一开始就围绕通配符捕获设计 map,这样既守住平台规则上限(Vercel 的 1,024 条),也避免重定向链。
FAQ
- 重定向要保留多久? Google 说至少 180 天,只要旧 URL 还在收到 Search 流量就更久。因为外链能活过这个窗口,建议无限期保留。
- 永久迁移用 301 还是 302? 用永久重定向(
301,或 Vercel"permanent": true发出的308)。302/307是临时的,会让 Google 继续收录旧 URL,排名信号传不全。 - 真有必要让旧域名的托管一直活着吗? 有。重定向只有在旧域名上有服务器、且持有效证书并响应时才会触发。彻底关停旧主机,每条旧 URL——以及指向它的每条外链——都会失效。
- 我的站有 5 万条 URL,撞到了 Vercel 的 1,024 上限,怎么办? 把 1:1 规则收成通配符捕获(
/blog/:slug一条就覆盖所有博文)。对实在不规则的映射,用 Vercel Bulk Redirects(每项目最多 1,000,000 条)或写一段从列表里查目标的 Edge Middleware。 - 查询参数和结尾斜杠会跟着重定向保留吗? 不会自动保留。Vercel 和 Netlify 默认保留查询字符串,但结尾斜杠的行为要你自己对齐;在
curl抽样里把/blog/foo和/blog/foo/都测一遍。