← 知识整理
出海增长 / 知识整理 · 中文

JavaScript SEO 全套(基础 + 诊断 + 动态渲染 + 懒加载)

Google 处理 JavaScript 的 3 阶段(crawl 抓取 / render 渲染 / index 索引) + render queue 渲染队列机制 + WRS(Web Rendering Service,网页渲染服务)。15 条最佳实践 + 11 步诊断清单。SPA(单页应用)必坑:soft 404(软 404) / fragment 路由 / Local Storage 失效 / cache 指纹 / robots meta 用 JS 注入的陷阱 / Web Components 的 shadow DOM。Dynamic rendering(动态渲染)已是历史变通方案,推荐用 SSR / 静态 / hydration 替代。懒加载用 viewport(视口)检测 + 无限滚动改成分页 URL。Web Components 必用 Slot。

资料来源:Google 搜索与 SEO · 本站发布:2026-09-26 · 笔记更新:2026-05-17

SEO搜索引擎自然增长

Google 搜索是唯一默认会跑 JavaScript 的主流搜索引擎(用 evergreen Chromium,常青版 Chromium)。其它搜索引擎(Bing 部分支持、DuckDuckGo / Yandex / 多数小众引擎)不跑 JS — SSR 服务端渲染仍是最安全的选择。

Google 处理 JavaScript 站点的核心机制:WRS(Web Rendering Service,网页渲染服务) + render queue(渲染队列)。


1. Google 处理 JavaScript 的 3 阶段 + 渲染队列

URL
 ↓
[crawl queue 抓取队列] → Googlebot 取 URL → 检查 robots.txt
 ↓
fetch HTML → parse 解析 → 抽取链接回 crawl queue
 ↓
[render queue 渲染队列] → WRS(无头 Chromium)跑 JS → 渲染后 HTML
 ↓
parse 解析渲染后的 HTML → 抽链接回 crawl queue + 用于 indexing 索引
 ↓
[index 索引]

关键不变量:

  • 所有 HTTP 200 页面都进 render queue,无论是否含 JS(Google 自己判断)
  • 非 200(如 404)可能跳过渲染
  • 渲染可能等几秒到更久 — 由 Google 资源决定
  • WRS 用当前 evergreen Chromium,跟最新 Chrome 同步
  • 被 robots.txt block 阻止的资源 → 不会被 fetch 抓取 → 渲染缺资源 → Google 可能看不到内容

反直觉:渲染队列是异步的。如果你 hash 改了页面但渲染队列堵着,Google 看到的可能是几天前的快照。


2. 15 条 JavaScript SEO 最佳实践(必看)

按重要性排序。

2.1 内容相关

# 实践 关键点
1 仍用 SSR(服务端渲染)/ 预渲染 给用户和抓取器都更快,非 Google 抓取器也能看到
2 唯一描述性 <title> + meta description JS 设置 OK,但确保渲染完成时这俩存在
3 用 <a href> 而不是 onclick Google 只从 <a href> 抓链接
4 History API 而不是 URL fragment(片段) #/products 这种 fragment 路由 Googlebot 不可靠(AJAX crawl scheme 2015 已废弃)
5 加 结构化数据 用 JSON-LD,JS 注入也 OK 详见 Structured Data 完全总览 (框架 + 34 个 rich result type 一键查 + JSON-LD/Microdata/RDFa 选型)
6 Web Components 用 <slot> 显示 light DOM(明亮 DOM) 否则 light DOM 内容不进渲染 HTML → 不被索引
7 懒加载用 viewport(视口)检测,不是用户 scroll(滚动) Google 不滚动你页面

2.2 错误处理

# 实践 关键点
8 用准确 HTTP 状态码 404 表示 not found / 401 表示 login wall 登录墙 / 301 表示 moved 已迁移
9 SPA 单页应用避免 soft 404(软 404) 客户端路由经常发 200 当作 not-found → 假 200 会被索引。改用 JS 重定向到真 404 URL,或注入 <meta name="robots" content="noindex">
10 Robots meta 标签用 JS 注入要小心 Google 看到 noindex 可能跳过渲染 → JS 想去掉 noindex 不可靠;如果想被索引,原始 HTML 里别有 noindex

2.3 性能 / 缓存

# 实践 关键点
11 长寿命缓存 + 内容指纹(content fingerprinting) WRS 可能忽略 cache header,用 main.2bb85551.js 这种 hash 文件名避坑
12 特性检测(feature detection) + polyfill 补丁 检测 API 不支持,提供 fallback 退路;某些(如 WebGL)Google 不支持,要 SSR 那部分
13 用 HTTP,不依赖 WebSockets / WebRTC Googlebot 只发 HTTP,其它连接类型用不了

2.4 规范化(Canonical)/ 机器人(Robots)

# 实践 关键点
14 rel="canonical" 优先放 HTML 实在要 JS 注入 OK,但只能保留 1 个 canonical;不要 JS 改成跟原 HTML 不同的值
15 Camera / Geo / Notification 等权限请求不要强求 Googlebot 拒绝权限请求;给个不要权限也能用的路径

3. SPA(单页应用)必坑 6 大

坑 症状 修法
soft 404 软 404 客户端路由 not-found 返 200 → 假错页被索引 JS 重定向到真 404 URL,或注入 <meta robots="noindex">
fragment 路由(#/products) Googlebot 抓不到 fragment 后面的内容 History API:window.history.pushState({}, '', '/products')
Local Storage / Session Storage 失效 跨 page load 数据丢 WRS 每次 page load 都清空 Local / Session Storage 和 Cookie。不能依赖持久化数据 serve 内容
WebSocket / WebRTC 拉数据 Googlebot 拿不到 给 HTTP fallback 退路
JS 改 canonical 多个 canonical 冲突 → 行为不可预测 同一页只能 1 个 canonical,JS 注入前先检查
JS paywall(付费墙)假实现 全文藏 HTML 里 + JS 隐藏 实际限制访问要服务端做。JS 隐藏只是装样子

4. 诊断清单 11 步

怀疑 JavaScript 阻碍索引时:

  1. 跑 Rich Results Test / URL Inspection Tool — 看加载的资源 / JS 控制台 / 异常 / 渲染后 DOM。Search Console 的 Crawl Stats Report(抓取统计报告)监控 Googlebot + WRS 活动
  2. 防 soft 404 — 见 §3 第 1 条
  3. 预期 Googlebot 拒绝权限请求 — 不强求 Camera / Geo / Notification
  4. 不用 URL fragment 加载不同内容 — 用 History API
  5. 不依赖数据持久化 — WRS 每次清 Local / Session / Cookie
  6. content fingerprinting 内容指纹 — main.<hash>.js 防 cache 缓存旧资源
  7. 特性检测 + 关键 API 的 fallback / polyfill
  8. HTTP 连接才行 — 不用 WebSocket / WebRTC 抓主内容
  9. Web Components 渲染正确 — <slot> 用了吗?Rich Results Test 看渲染后 HTML 内容齐不齐
  10. JS paywall 实现方式 — 完整内容不要在 HTML 里
  11. 修完再测一遍 — 拿 Rich Results Test / URL Inspection 复验。绿勾通过

收集生产环境的 JS 错误:推荐打 global onerror handler(全局错误处理器),把 Googlebot 和真实用户的 JS 错误都 log 日志到远程,定位渲染失败的原因。

window.addEventListener('error', function(e) {
    const errorText = [
        e.message,
        'URL: ' + e.filename,
        'Line: ' + e.lineno + ', Column: ' + e.colno,
        'Stack: ' + (e.error && e.error.stack || '(no stack trace)')
    ].join('\n');
    // POST 到自己服务器
    fetch('/logError', { method: 'POST', body: errorText });
});

5. Dynamic Rendering(动态渲染)是历史变通方案(2026 不推荐)

结论:别用 dynamic rendering。已经从推荐方案降级,用 SSR / 静态渲染 / hydration 替代。

5.1 它干什么

请求 → 检测 user-agent
  ├─ Googlebot / 不支持 JS 的抓取器 → 路由到 rendering server 渲染服务器 → 返回静态 HTML
  └─ 普通浏览器 → 返回 client-rendered 客户端渲染版本

5.2 为什么弃用

  • 增加服务器复杂度(双轨服务)
  • 维护成本高
  • SSR / hydration 同样解决问题且更简单
  • 真"抓取器列表"难维护,新 bot 出来你没适配

5.3 它不算 cloaking(掩饰违规)的条件

只要 dynamic rendering 给两边的内容相似(server-rendered 服务端渲染版 ≈ client-rendered 客户端渲染版),Googlebot 不视为 cloaking。

真 cloaking(违反 Google SEO 入门 + Search 工作原理 + Search Essentials §7 spam 政策)的例子:给用户看猫,给抓取器看狗。

5.4 现代替代方案

方案 适用
SSR(Server-Side Rendering 服务端渲染) 默认推荐。Next.js / Nuxt / Astro 等
静态渲染(Static rendering) 内容不常变 → 构建时生成 HTML
Hydration(注水) SSR + 后续客户端接管交互
预渲染(Pre-rendering,类 SSR) 小站省事

6. Lazy Loading(懒加载)正确做法

6.1 核心原则

懒加载必须用 viewport(视口)检测,不是 scroll(滚动)触发。Google 不滚动你的页面。

6.2 3 个实现方式

方式 何时用
浏览器内置 loading="lazy"(<img> / <iframe>) 现代浏览器原生支持,最简单
IntersectionObserver API + polyfill 自定义逻辑、视频懒加载
JS 库(react-lazyload 等) 框架集成

6.3 不要的

  • 不要对首屏可见内容用懒加载(慢且毫无意义)
  • 不要靠 scroll(滚动)事件触发(Google 不 scroll)

6.4 Infinite scroll(无限滚动)的正确实现

无限滚动跟 SEO 天然矛盾,要 paginated 分页化:

6.5 验证

Search Console 的 URL Inspection Tool → Live URL → 看渲染后 HTML:

  • <img src> / <video src> 真实 URL 都在 → 成功
  • 全是 placeholder URL(占位 URL)→ 失败,Google 没看到真图

7. 关键速查表

想做 怎么做 警告
设页面 title JS 设置 OK 确保渲染完成时 title 存在
加结构化数据 JS 注入 JSON-LD 详见 Structured Data 完全总览 (框架 + 34 个 rich result type 一键查 + JSON-LD/Microdata/RDFa 选型)
设 canonical 优先 HTML;JS 注入 OK 同页只能 1 个,不要冲突
设 robots meta 优先 HTML noindex 可能跳过渲染 → JS 改不掉
路由(SPA) History API 不要 URL fragment(#/foo)
处理 404 JS 重定向到真 404 URL,或注入 noindex 客户端假 200 会被索引
加图懒加载 viewport(视口)检测 不要 scroll(滚动)触发
实现无限滚动 分页 URL + History API 更新 每 chunk 块独立持久 URL
检测 API 支持 特性检测 + polyfill WebGL / WebSocket 等 Google 不支持
拿数据 HTTP fetch 不要 WebSocket / WebRTC 拉主内容
跨页面持久化 服务端 WRS 每次清 Local / Session / Cookie
加缓存控制 内容指纹(content fingerprinting) WRS 可能忽略 cache header
Web Components <slot> 显示 light DOM(明亮 DOM) shadow DOM 影子 DOM only 不被索引
Paywall 付费墙 服务端控制完整内容 JS 隐藏不算限制

8. 跟其它 wiki 的关系

想知道 去
Crawling 抓取整体机制 / Googlebot 详情 Googlebot 抓取机制与索引控制完全指南 (URL/Links/Mobile-first/Meta/Testing/AMP)
canonical 完整玩法 Canonical / 重定向 / 网站迁移完全指南 (含 HTTP 状态码全表 + 503 临时停业 playbook)
robots.txt + robots meta 抓取与索引控制完全指南 (robots.txt / noindex / X-Robots-Tag / data-nosnippet / rel)
结构化数据 33 种 Structured Data 完全总览 (框架 + 34 个 rich result type 一键查 + JSON-LD/Microdata/RDFa 选型)
pagination 完整实践 Ecommerce SEO 完全指南 (6 Surface / 4 Launch 策略 / Merchant Center / 6 SD 类型 / Pagination 3 模式 / Review 13 准则)
Search Console 监控 Search Console + Analytics + Trends 三件套用法 (流量诊断 / 关键词调研 / Looker Studio)
SEO 全景 / Search 原理 Google SEO 入门 + Search 工作原理 + Search Essentials

来源与关联资料