双语站只跑在一个 hosting 区域,意味着总有一边受众看到的是慢版本。源站在 us-central1(爱荷华),上海的读者要等首字节横跨太平洋,CDN 也救不了。把每种语言放到自己的子域、指向离它最近的区域——en.yoursite.com 在美国或欧洲,zh.yoursite.com 在香港、新加坡或东京——就能让源站贴近各自受众。配得好,能给较远那种语言砍掉 200-400ms 的 TTFB,同时不拆 SEO,也不破坏共享资源。
一句话结论
- 只有当两边受众分处不同大洲、且 analytics 显示 TTFB 明显偏向一边时,才按语言拆子域。否则就留在语言前缀路径(
/en/、/zh/)——更简单,SEO 上也等价。 - 纯静态托管(Cloudflare Pages、Vercel、Netlify)本来就走全球 CDN,拆区域收益很小。真正划算的场景是单区域源站——Firebase Hosting/App Hosting、App Engine、Render、fly.io。
- 每个子域要有自己的部署目标、SSL 证书、sitemap,以及一个自指 canonical。hreflang 必须在两个子域之间双向对称,否则 Google 会忽略整组。
- 对中国大陆读者,把站放在香港或新加坡并不能绕过防火墙。流量照样要穿墙,相比香港本地访问大约多 2 倍延迟、5 倍丢包。真正的中国大陆快速体验需要大陆托管加 ICP 备案——那是大得多的投入。
什么时候值得拆
只有症状明确时才上这套方案:
- analytics 显示某种语言的 TTFB 超过 800ms,且这种语言的受众在源站的地球另一端。
- 同样内容出双语,但只有一个区域的用户抱怨速度。
- 已经在用语言前缀 URL,SEO 没问题——唯一不平衡的是性能。
- 账单显示大头流量出自某一个区域,另一个闲着。
如果你用的是全球 CDN 的静态托管,比如 Cloudflare Pages(截至 2026 年 6 月有 300+ 边缘节点)或 Vercel(约 30 个区域),你的 HTML 本来就缓存在两边受众附近,拆区域几乎没收益。真正有意义的,是你有一个固定单源站、且动态响应无法在边缘缓存的情况。
DNS 和 hosting 布局
每个子域是各自区域的部署目标。DNS 记录长这样:
en.yoursite.com CNAME cname.vercel-dns.com # 美/欧区域
zh.yoursite.com CNAME yoursite-zh.web.app # asia-east1(台湾)
yoursite.com A 76.76.21.21 # 301 到默认语言
www.yoursite.com CNAME cname.vercel-dns.com # 镜像 en. 或跳走
裸域名和 www 应根据 Accept-Language 301 到某个语言子域,或跳到一个轻量语言选择页。不要让裸域和子域同时承载内容——会冒出第三组 URL 跟子域抢同一份内容,稀释每一个信号。
跨子域的 canonical 和 hreflang
多数团队在这里出错,代价还很狠:只要一条 return tag 断了,Google 就会把整组 hreflang 丢掉。研究显示错误率约 75%,最常见的原因就是缺少 return tag。en.yoursite.com/articles/foo/ 上的每个页面声明自指 canonical,同时用 hreflang 指向 zh 版本:
<link rel="canonical" href="https://en.yoursite.com/articles/foo/">
<link rel="alternate" hreflang="en" href="https://en.yoursite.com/articles/foo/">
<link rel="alternate" hreflang="zh" href="https://zh.yoursite.com/articles/foo/">
<link rel="alternate" hreflang="x-default" href="https://en.yoursite.com/articles/foo/">
zh 页面写同样的结构,自指 canonical 指向 zh.yoursite.com 的 URL,并写上同一组双向 alternates。两个子域必须互相列对方——单向 hreflang 会被忽略。按 Google 官方文档,子域和语言前缀路径对 hreflang 完全等价,二选一只是运维取舍(DNS、托管、analytics),不是排名因素。所以别为 SEO 去拆。为延迟拆,并让 SEO 保持中立。
共享资源——挑一个 CDN 源
字体、图片、JS bundle 在两个子域都要用时,有两种模式:
- 每个子域各放一份。 简单,有重复,小 bundle 没问题。
- 共用一个资源子域(
cdn.yoursite.com)并配好 CORS。en和zh都从它拉,两边共享同一份缓存,代价是首次加载多一次 DNS 查询。
总资源约 500 KB 以下用方案 1;bundle 较大、有自定义字体,或想让两种语言共享一份缓存就用方案 2。无论哪种,都把这个 CDN 源放在全球边缘网络上(Cloudflare R2 + Pages,或 Vercel 的 CDN),这样两边受众都不会为资源付跨洋代价。
验证延迟收益
整套配置工作量不小。庆祝之前先验证。用 WebPageTest 或 Pingdom,从至少三个匹配受众的观测点测每个子域:一个美国城市、一个中国城市、一个中性第三点(新加坡是不错的中立锚点)。
盯两个数:TTFB(源站响应时间)和总文档加载时间。如果 zh.yoursite.com 从上海现在测出来 TTFB 约 200ms,而原来美国单源站是约 700ms,迁移就成了。如果数字几乎没动,多半是你的「亚洲」区域配错了——Firebase asia-east1 在台湾,不在中国大陆,北京读者的包仍要穿过防火墙。独立测量显示,仅防火墙的过滤就能把进入中国的传输拖慢多达 40%,而中国到香港的流量延迟约为香港本地的 2 倍、丢包约 5 倍。在宣告完工之前,换新加坡区域或 HK CDN 边缘再测一轮——也要对任何被承诺「中国很快」的人如实说明预期。
双区域部署流程
最干净的流程是单一来源、双目标交付。一次构建,用 regions.json(或每次部署的环境变量)选公开源站 URL 和最近的区域:
# CI:构建一次,分别部署到每个区域
npm run build
firebase deploy --only hosting:en --project en-us
firebase deploy --only hosting:zh --project zh-asia
Firebase App Hosting 现在允许每个 backend 直接指定区域(firebase apphosting:backends:create --location asia-east1),所以拆区域不再需要两个独立项目——一个项目里两个 backend 就够。
要预案两种失败模式。第一,一个区域成功、另一个失败——CI 设成任一失败就中止并回滚,否则线上几小时是半部署状态。第二,两边都成功但时间不同步,落后那边用户短时间看到旧内容。内容站还能接受,应用就难顶——应用要把两边钉到同一个 Git SHA 上,两边都验证完再切任何 feature flag。
容易踩的坑
- 忘了给第二个子域配 SSL。 站点能开但浏览器报不安全。多数托管按自定义域名自动签发证书;上线公告前先确认证书已签发。
- hreflang 不对称。
en列了zh但zh没列en。Google 忽略的是整组,不只是断掉的那一条。 - 把两个语言子域都 canonical 到同一个(通常是
en)。Google 会把另一种语言整个从索引里踢掉。 - Search Console 配错。 Domain 属性一次覆盖所有子域;URL 前缀属性只覆盖一个。如果用的是 URL 前缀,要把
en.和zh.各加为独立属性,否则一半收录数据看不到。 - sitemap 只列一个子域。 每个子域要有自己的 sitemap,只列自己的 URL。
- cookie/session 的 domain 设成单个子域而不是
.yoursite.com。在en.登录的用户一切到zh.就被登出。
FAQ
- 不用子域用
/en/路径行吗?: 路径方案更简单——一个 Search Console Domain 属性、一张 SSL 证书、一次部署——而且 Google 视为 SEO 等价。它唯一做不到的是给你区域级源站。如果源站延迟才是你的真问题,用子域;否则留在路径方案。 - Google 会把子域当独立站点吗?: 一定程度上是。每个子域权重各自累积,用 URL 前缀属性时还要各自在 Search Console 建一条(Domain 属性则一并覆盖)。互相内链有帮助,但绑定不如同域路径紧密。
- 站放香港或新加坡,中国大陆就快吗?: 不太能。中国到 HK/SG 的流量照样穿防火墙,会带来延迟、丢包和多达约 40% 的过滤拖慢。只有大陆托管才真正避开这次穿越——而那需要 ICP 备案,外资所有者只能通过境内主体(WFOE 或本地合作方)办理,至少预留 2-4 周。
- 用 ccTLD(
.cn、.com.cn)替代zh.怎么样?: ccTLD 是最强的地域信号,但要单独的域名所有权、ICP 备案,长期成本大约翻倍。多数独立开发者起步用子域更便宜。 - 同一套 host 能给每种语言跑两个区域吗?: Firebase 上部署两个 Hosting site(或两个 App Hosting backend),各自钉一个区域。Vercel 上建两个项目,各自指向各自的子域,边缘缓存交给 Vercel 的 CDN。
- 每个子域要单独的 analytics property 吗?: 用一个 property 并配好跨子域追踪,让读者从
en.切到zh.时还在同一个 session,而不是被记成新访客。
相关阅读
标签: #独立开发 #域名 #DNS #multi-region #双语