编程 全站每个 URL 都返回同样的 3,780 字节,Google 信了

2026-09-08 05:08:47

全站每个 URL 都返回同样的 3,780 字节,Google 信了

一天早上用 Googlebot user agent 检查:站点每个 URL 都返回同一个 3,780 字节的 shell——相同的 title、零 h1、零正文文本。首页、博客文章、产品页在 JS 执行前字节级相同。Search Console 跟爬虫站一边:741 个 URL 里 116 个在 28 天内只有一次曝光,上线五个月的落地页仍被报为"URL is unknown to Google"。

关键认知:Google 会渲染 JS,但那是另一回事

标准回复是"Googlebot 现在会执行 JS,你没事"——它确实执行,有几个页面被索引,渲染确实发生。但渲染是独立、有预算的队列:权威度低的域名分不到多少预算。所以实际问题不是"Google 能不能渲染",而是"Google 会不会在今天、在它决定这个页面讲什么之前,花预算渲染它"。

还有第二个与渲染无关的问题:741 个渲染前字节级相同的 URL 看起来像重复内容——你把重复内容信号递给爬虫,然后指望渲染队列补救第一印象

修复:post-build 注入真 head

写了个构建后脚本,往每个生成的 HTML 注入真实 <head>:title、description、canonical、robots、Open Graph、Twitter。只改 head,body 保持 SPA 原样——无 hydration 闪烁、无静态副本与用户所见漂移、无 cloaking 嫌疑(静态标记是渲染标记的子集,不是不同页面)。每个值都从 React 页面读的同一来源读取;组件里字面量 title 从组件源码提取,不让人重打一遍——"重打两次的数字迟早会自相矛盾"。

两个大坑

Trap 1:react-helmet-async 会删掉你没标记的标签。 shell 里有静态 <meta name="description">,Helmet 挂载时设置自己的。假设"后者胜出"——实际:Helmet 首次提交会移除所有带 data-rh 的标签并重插自己的;不带该属性的存活。于是静态标签留着、Helmet 标签加上,页面带两个 description,静态的在前,爬虫读的就是它——全站博客都在宣传首页通用文案。修法:给 Helmet 真正会重加的标签打标记 data-rh="true"。锐边:只标记 Helmet 会重加的——不重加的 data-rh 标签挂载时被删了就不回来,他们给 og:image 打了标记,全站分享图丢了才发现。另一个 bug:正则按属性顺序匹配,<meta name="description" ...> 匹配不了 shell 写出的 <meta data-rh="true" name="description" ...>——按包含 key 匹配,永远别按属性顺序

Trap 2:脚本读了 sitemap,但没人重新生成 sitemap。 这是最花时间、也最与 SPA 无关的坑。

实践建议

  • CSR 站点做 SEO:先确认 Googlebot 视角(含正文、title、h1 的完整 HTML),别假设渲染队列会兜底;
  • head 注入只加 head、body 不动,避免 cloaking 与副本漂移;
  • 用 Helmet 类库时搞清 data-rh 生命周期,静态与动态 meta 并存会出双 description。

来源:Our site served every URL the same 3,780 bytes, and Google believed it - DEV Community

复制全文 生成海报 SEO React 前端 实践

推荐文章

程序员茄子在线接单