简体中文
别让多语言 SEO 白做:hreflang 替代标签在 VitePress 中的正确落地

背景:当主语言遇上历史包袱
如果你用 VitePress 搭建了多语言站点,并且辛辛苦苦把内容翻译了一遍,却发现在 Google 或 Bing 里搜不到对应的语言版本,甚至两个版本在互相抢夺排名,那么你大概率漏掉了一个极其关键的 SEO 标签:hreflang。
在展开聊技术之前,我想先聊聊这个博客的“历史包袱”。
我的博客前期只有中文内容,默认无前缀路径就是主语言(https://fishfinal.com/)。后期重构时,为了走向国际化,我引入了 VitePress 的 i18n,增加了英文版(/en/)。
这时就面临一个尴尬的架构问题:如果我此时把主语言(x-default)强行切换为英文,意味着要把所有中文文章移动到 /zh/ 下,不仅建站成本极高,而且会导致搜索引擎前期已经收录的旧中文链接全部 404,彻底打乱现有的 SEO 索引。
因此,为了兼顾历史收录,我依然将中文作为了当前的 x-default(兜底页面)。
💡 给新站长的建议: 如果你的博客是全新站点,准备直接做多语言。强烈建议默认根目录就放英文(
/),中文放到/zh/下,并将x-default指向英文。这样更符合国际化的通用标准。但如果是像我这样的存量老站,保持原有主语言作为兜底是最稳妥的选择。
今天我们就来聊聊,为什么多语言站必须加 hreflang,它在搜索引擎眼中到底起什么作用,以及如何在 VitePress 中优雅地、动态地落地它。
一、 为什么搜索引擎会“犯傻”?
假设你有一篇关于“MinIO 编译部署”的文章,有中文版和英文版。如果你不做任何声明,搜索引擎爬虫抓取到这两个页面时,会面临一个尴尬的局面:
- 内容几乎一致:在搜索引擎看来,这两个页面高度相似,可能被判定为“重复内容”。
- 自我竞争:中文用户搜相关关键词时,Google 可能把英文页面排在前面;英文用户搜索时,反而展示中文页面。
- 互相稀释权重:多个相似的 URL 分散了外链和页面权重,导致谁也排不到前列。
没有 hreflang,搜索引擎只能靠自身的语言检测模型去猜,而猜的准确率并不稳定,尤其是在简繁体、或者地区变体(如 zh-CN 和 zh-TW)上。
二、 hreflang 到底是什么?
简单来说,hreflang 替代标签就是告诉搜索引擎:“这个页面还有其他语言/地区的版本,它们的地址在这里,请把它们推荐给对应语言的用户。”
它有三个核心作用:
- 精准定向:把中文页推给中文用户,英文页推给英文用户,提升点击率和转化率。
- 避免自我竞争:明确告诉搜索引擎“这些是平级的替代版本,不是抄袭”,从而保护页面权重。
- 优化目标市场体验:在搜索结果中,直接展示符合用户母语的标题和摘要。
⚠️ 重要提示:
hreflang是信号而不是指令。搜索引擎会参考它,但最终展示哪个版本,仍由搜索引擎的算法决定。
三、 高频误区:canonical 能替代 hreflang 吗?
绝对不能。 这是很多开发者最容易踩的坑。
canonical(规范标签):它的作用是“合并”。当你网站有多个相同的 URL(比如带?参数的 URL),你用canonical告诉搜索引擎:“这些都是同一个页面,请把权重都算在主 URL 上。”hreflang(替代标签):它的作用是“平级替代”。中英文版本是独立且平等的,各自服务不同语言的用户,它们不是互相取代的关系。
如果错误地把中文页的 canonical 指向英文页,会导致中文页彻底从索引中消失。
四、 VitePress 中的正确落地写法
在 VitePress 中配置 hreflang,最直观的做法是在 config.mts 的 head 数组里直接写死;但如果你想一劳永逸,则应该使用 VitePress 提供的钩子动态生成。
1. 基础版:硬编码示例
假设你的主域名是 https://yourdomain.com,文章路径是 /posts/xxx.html。中英文的 URL 结构如下:
- 中文版:
https://yourdomain.com/posts/xxx.html - 英文版:
https://yourdomain.com/en/posts/xxx.html
你可以在 config.mts 中直接注入:
typescript
// .vitepress/config.mts
export default defineConfig({
// ... 其他配置
head: [
// ... 其他标签(如 favicon 等)
[
'link',
{
rel: 'alternate',
hreflang: 'zh-CN',
href: 'https://yourdomain.com/posts/xxx.html'
}
],
[
'link',
{
rel: 'alternate',
hreflang: 'en',
href: 'https://yourdomain.com/en/posts/xxx.html'
}
],
[
'link',
{
rel: 'alternate',
hreflang: 'x-default',
href: 'https://yourdomain.com/en/posts/xxx.html' // 建议:新站点的兜底页面通常设为英文
}
]
]
})(注:这种方式虽然简单,但如果你的博客有几十上百篇文章,硬编码简直是灾难,每加一篇文章都要改配置。)
2. 进阶版:使用 transformHead 动态生成(生产级)
为了解决硬编码的痛点,我们可以使用 VitePress 提供的 transformHead 钩子,根据当前页面的 relativePath 动态生成多语言标签。以下是实际生产环境中的配置方案:
typescript
// .vitepress/config.mts
import { defineConfig, HeadConfig } from 'vitepress';
export default defineConfig({
// ... 其他配置
transformHead({ pageData }) {
const { frontmatter, relativePath } = pageData;
const metas: HeadConfig[] = [];
// 1. 判断当前语言环境
const isEn = relativePath.startsWith('en/');
// 2. 获取除去语言前缀后的纯路径(比如 'posts/xxx.md')
const purePath = relativePath.replace(/^(zh|en)\//, '');
// 3. 构建中文和英文的绝对 URL
let zhUrl = `https://fishfinal.com/${purePath.replace(/\.md$/, '.html')}`;
let enUrl = `https://fishfinal.com/en/${purePath.replace(/\.md$/, '.html')}`;
// 4. 处理首页的特殊情况
if (purePath === 'index.md') {
zhUrl = 'https://fishfinal.com/';
enUrl = 'https://fishfinal.com/en/';
}
// 5. 注入 hreflang 标签(双向互指)
metas.push(['link', { rel: 'alternate', hreflang: 'zh-CN', href: zhUrl }]);
metas.push(['link', { rel: 'alternate', hreflang: 'en', href: enUrl }]);
// 注意:这里将 x-default 指向了 en。因为对于世界上非中英语言的用户,英文界面的接受度更高。
// 如果你想把中文作为兜底,修改为 zhUrl 即可。
metas.push(['link', { rel: 'alternate', hreflang: 'x-default', href: enUrl }]);
return metas;
}
})必须遵守的 3 条铁律
无论你用哪种方式,都必须满足以下条件:
- 必须双向互指:中文页里必须声明英文页的链接,英文页里必须声明中文页的链接。单向声明是无效的。(动态方案已自动处理此逻辑)。
- 必须使用绝对路径:一定要写完整的
https://开头的 URL,不要用相对路径。 x-default兜底:当用户的搜索语言既不是中文也不是英文时,搜索引擎会展示x-default指向的页面。通常建议设为英文,这样能照顾到全球更多语种的用户。
五、 实战上线避坑指南
当你满怀期待地把加了 hreflang 的代码推送到线上后,接下来的操作也很关键。
1. 不要频繁重新提交 Sitemap!
很多站长一改代码,就跑去 Google Search Console (GSC) 或 Bing Webmaster Tools 重新提交 sitemap.xml。这是完全错误的。 Sitemap 只是指路的地图,只负责声明 URL 列表。只要你的 URL 列表没有发生增减,就不需要重新提交。频繁提交反而可能降低搜索引擎对 Sitemap 的信任度。

2. 正确的催更姿势:URL 检查
如果你想让改过标签的页面立刻被收录,不要去折腾 Sitemap,而是去使用“网址检查”:
- 打开 Google Search Console (或 Bing)。
- 在顶部的“网址检查”输入框里,粘贴你刚改过
hreflang的具体英文页 URL,点击“请求编入索引”。 - 再粘贴对应的中文页 URL,同样操作一次。
这样能强制爬虫在最快时间重新抓取这两个页面,立刻发现你的改动。
3. 验证是否生效
等一两天后,在线上页面右键点击“查看网页源代码”,搜索 hreflang,确认这几行代码是否如预期出现在 <head> 中,并且绝对路径完全正确。

总结
多语言站点的建设成本极高,不要让粗心大意毁了你的 SEO 努力。花 10 分钟把 hreflang 配好,并严格遵守双向互指的原则,你的多语言流量才能真正源源不断。
