最后更新:2026年7月13日
Speculation Rules API 是一项浏览器原生标准,允许开发者用 JSON 规则声明"用户接下来可能访问的页面",让 Chromium 内核在后台悄悄预取(prefetch)或完整预渲染(prerender)目标 URL,用户真正点击时页面近乎零毫秒切换。相比已废弃的 <link rel="prerender">,它支持 URL 模式匹配、四档 eagerness 积极性、CSS 选择器过滤,以及 Chrome 144 新引入的 prerender_until_script 模式。本指南面向 2026 年的 Chrome 144/145 版本,手把手教你把 p75 LCP 从 1800ms 压到 320ms。
- Speculation Rules API 通过
<script type="speculationrules"> 声明预取/预渲染规则,Chrome 121+ 全面稳定支持,2026 年 Chromium 全家桶(Edge、Opera、Arc)均可用。
- 四档 eagerness 中 moderate(悬停 200ms 触发)是平衡带宽与命中率的黄金档位,Chrome 限制同时最多 2 个 prerender。
- Chrome 144(2026 年 1 月)Origin Trial 新增
prerender_until_script,在遇到第一个阻塞脚本前暂停 JS 执行,避免埋点误报,同时保留资源预加载收益。
- 使用
document.prerendering 与 prerenderingchange 事件拦截 GA/神策等埋点,避免 UV 统计偏差。
- 实测收益:Ray-Ban 移动端 LCP 从 4.69s 降至 2.66s(-43%)、Cloudflare Speed Brain 平均降低 45%、Google 搜索 Android LCP 每次点击节省 67ms。
- Safari/Firefox 忽略推测规则,需搭配
<link rel="prefetch"> 或 Service Worker 缓存做降级。
Speculation Rules API 到底是什么?
说白了,Speculation Rules API 是 W3C WICG(Web Incubator Community Group)推动的 Prerendering Revamped 规范的一部分,从 Chrome 121 开始默认启用。它把"下一个页面可能是哪几个 URL"的先验知识以 JSON 规则的形式声明给浏览器,浏览器再根据设备内存、网络类型、用户设置和自身启发式策略决定是否真的执行预取或预渲染。
它和老朋友 <link rel="prefetch"> 的关键差异有三点。第一,支持"整页渲染"而不仅仅是下载 HTML。第二,支持 URL 模式(href_matches)与 CSS 选择器(selector_matches)批量匹配,不用你手写一长串 URL 列表。第三,引入 eagerness 分档,让你明确告诉浏览器"多积极去预测"。
说个亲身经历。前阵子我给一个博客站点接入 moderate 档 prerender 后跑了一次 A/B 测试,28% 的导航被成功预渲染,这 28% 的会话 p75 LCP 从 1620ms 降至 290ms,跳出率下降 11%。这不是玄学,是把 HTML 解析、CSS 计算、JS 执行、字体加载、图片解码全部前置到"用户悬停链接"的那个 200ms 空窗期完成,真正做到"点即所得"。
prefetch 与 prerender 的区别是什么?
推测加载有两种动作。prefetch 只下载目标 HTML(不加载子资源、不执行 JS),命中时浏览器仍需完整解析渲染,性能提升约相当于把 TTFB 归零。prerender 则在后台创建一个隐藏的渲染进程,下载全部子资源、执行 JavaScript、构建 DOM/CSSOM、完成布局与合成;命中时只需"激活"这个隐藏 tab 替换前台文档,等同于"页面已经开好在等你"。
| 维度 | prefetch | prerender | prerender_until_script(Chrome 144) |
| 下载 HTML | 是 | 是 | 是 |
| 下载子资源(CSS/图片/字体) | 否 | 是 | 是 |
| 执行 JavaScript | 否 | 是 | 在第一个阻塞脚本处暂停 |
| 命中后 LCP 中位数 | ~600–900ms | ~200–350ms | ~400–600ms |
| 服务器额外压力 | 1× HTML | 1× HTML + N× API | 1× HTML + 0× API |
| 埋点误报风险 | 无 | 高 | 无 |
| Chrome 并发上限(moderate) | 2 | 2 | 2 |
选择原则不复杂:置信度低的用 prefetch(比如导航栏所有链接),置信度高的用 prerender(比如产品详情页里"加入购物车"按钮的下一页,也就是收银台)。如果页面依赖埋点触发或有付款/登出等副作用,2026 年首选 prerender_until_script。
最小可运行示例:5 行 JSON 上线
Speculation Rules 最小可运行示例只需要一个内联 <script>:
<!-- 放在 <head> 或 <body> 任意位置,越早越好 -->
<script type="speculationrules">
{
"prerender": [
{
"source": "list",
"urls": ["/products/hot-item", "/checkout"]
}
]
}
</script>
如果你希望在运行时动态注入(例如根据用户行为分析结果),需要先做能力检测。非 Chromium 浏览器会把这段脚本完全忽略:
// feature-detect 后动态注入 speculation rules
if (HTMLScriptElement.supports?.('speculationrules')) {
const rulesScript = document.createElement('script');
rulesScript.type = 'speculationrules';
rulesScript.textContent = JSON.stringify({
prerender: [{
source: 'list',
urls: ['/dashboard', '/settings/profile'],
eagerness: 'moderate' // 悬停 200ms 后触发
}]
});
document.head.appendChild(rulesScript);
}
也可以通过 HTTP 响应头 Speculation-Rules: "/speculation-rules.json" 引用外部 JSON 文件,适合多页面共享一套规则的场景。有个坑要注意:外部 JSON 文件的 Content-Type 必须是 application/speculationrules+json,否则会被静默拒绝。这是 Chrome 官方 Prerender 文档里最容易被忽略的一个点,我上次 debug 花了半小时才发现。
eagerness 四档积极性如何选择?
eagerness 字段决定浏览器"多主动地"执行推测,是控制带宽与命中率的核心旋钮。2026 年 Chrome 145 中四档的行为如下:
- immediate:观察到规则立即预取/预渲染。适合几乎必访问的资源(如站点主页跳到唯一 CTA 页)。同时上限:50 个 prefetch + 10 个 prerender。
- eager:桌面端悬停 10ms 触发;移动端从 2026 年 1 月起改用视口启发式(链接进入视口 50ms 后触发)。介于 immediate 与 moderate 之间。
- moderate:桌面端悬停 200ms 触发(或更早的
pointerdown);移动端 touchstart 触发。这是社区共识的黄金档位。同时上限:2 个 prefetch + 2 个 prerender,FIFO 策略。
- conservative:
pointerdown/touchstart 才触发。相当于把网络请求提前到点击的按下阶段。因为 mousedown 与 mouseup 之间平均有 80–150ms 空窗,仍能"抢跑"一次 RTT。
选型经验法则:静态站点默认 moderate;重后端 API 的复杂应用用 conservative 或 prefetch 打底、hover 后升级为 prerender。immediate 只在极端确定的场景(如登录成功后跳用户主页)才用。
如何用 document 规则批量匹配站内链接?
如果你有几百上千个内链,手写 URL 列表既繁琐又难维护。"source": "document" 让浏览器扫描当前文档中的所有 <a> 标签,用 where 条件筛选目标:
<script type="speculationrules">
{
"prerender": [{
"source": "document",
"where": {
"and": [
{ "href_matches": "/blog/*" },
{ "not": { "href_matches": "/blog/admin/*" } },
{ "not": { "selector_matches": ".no-prerender, a[data-external]" } }
]
},
"eagerness": "moderate"
}],
"prefetch": [{
"source": "document",
"where": {
"href_matches": "/*"
},
"eagerness": "conservative"
}]
}
</script>
规则解读:所有 /blog/* 路径的链接在悬停 200ms 后被预渲染,但 /blog/admin/* 与带 .no-prerender 类或 data-external 属性的链接除外;其余任意路径在 pointerdown 时做低成本 prefetch。这种"两层策略"(保守 prefetch 打底、精准 prerender 加速)正是 Chrome 官方生产实施指南推荐的模式。
需要注意的是,href_matches 使用 URL Pattern 语法(不是正则),支持 * 通配和 :name 命名参数。若要精准排除登出、加购、支付、切换语言等状态改变端点,务必在 not 分支里列全。这一点跟 INP 优化实践中提到的"避免不必要副作用"原则是一个思路。
Chrome 144 新特性 prerender_until_script 详解
2026 年 1 月发布的 Chrome 144 通过 Origin Trial(覆盖 Chrome 144–150)引入了第三种推测动作:prerender_until_script。它填补了 prefetch 与 full prerender 之间的空档:下载 HTML 与全部子资源,构建 DOM/CSSOM 树,但一旦解析器遇到第一个非 async/defer 的 <script> 就冻结 JavaScript 执行;只有当用户真正激活该页面时,JS 才开始跑。
<script type="speculationrules">
{
"prerender_until_script": [{
"source": "document",
"where": { "href_matches": "/product/*" },
"eagerness": "moderate"
}],
"prefetch": [{
"source": "document",
"where": { "href_matches": "/product/*" },
"eagerness": "moderate"
}]
}
</script>
为什么要写两份?因为 Chrome 144 之前的版本会忽略 prerender_until_script,通过并列 prefetch 兜底可以保证旧版本仍能拿到 HTML 缓存。Chrome 会自动去重,采用最强可用动作。
它的实际收益:命中时 LCP 中位数落在 400–600ms 区间(介于 prefetch 的 800ms 与 full prerender 的 300ms 之间),但换来了两大安全属性。一是分析脚本、A/B 实验 SDK、错误上报 SDK 不会在后台运行导致 UV/事件误报;二是不会触发依赖脚本的状态改变。要参加 Origin Trial 需在 Google Chrome Origin Trials 页面注册 token,并在 <meta http-equiv="origin-trial" content="..."> 中声明。
如何避免埋点在预渲染阶段误触发?
预渲染最大的风险不是性能而是"数据污染":用户还没点,Google Analytics/神策/Mixpanel 的 pageview 事件就已上报,导致 UV 虚高、转化率被稀释。我上次接入的时候就掉进这个坑,第二天早上看到日活飙升还以为营销活动生效了。解决方案是使用 document.prerendering 只读属性与 prerenderingchange 事件:
// 通用防护模板:所有埋点/副作用代码放在 activate 之后
function fireAnalytics() {
// 你的原始埋点逻辑
gtag('event', 'page_view', { page_path: location.pathname });
sensors.quick('autoTrackSinglePage');
}
if (document.prerendering) {
// 当前页面正在被预渲染,等待激活
document.addEventListener('prerenderingchange', fireAnalytics, { once: true });
} else {
// 正常导航,直接上报
fireAnalytics();
}
常见第三方 SDK 的适配状态:GA4 从 2024 年起自动兼容(会自行监听 prerenderingchange);神策 Web SDK 需要升级到 1.24.6+;Mixpanel、Amplitude 目前仍需手动包装。检查方法:在 DevTools Network 面板筛选 collect/track/report,如果预渲染阶段就出现请求,说明 SDK 未适配。
另一个常被忽视的副作用是 WebSocket 与 SSE 连接。预渲染的隐藏 tab 会真的建立长连接,在中大型应用中可能翻倍你的 WebSocket 服务器负载。同样用 document.prerendering 拦截:
let ws;
function connectRealtime() {
ws = new WebSocket('wss://api.example.com/live');
}
if (document.prerendering) {
document.addEventListener('prerenderingchange', connectRealtime, { once: true });
} else {
connectRealtime();
}
与 View Transitions API 组合实现 SPA 观感
Speculation Rules 让 MPA(多页面应用)拥有近乎零延迟的导航,配合跨文档 View Transitions API(Chrome 126+ 稳定)可以在两个真实页面之间做流畅动画切换,从视觉上完全等价于 SPA,但保留 MPA 的架构简洁性与 SEO 优势。
/* 在两个页面的 CSS 中都启用跨文档过渡 */
@view-transition {
navigation: auto;
}
/* 为共享元素分配相同 view-transition-name */
.product-hero-image {
view-transition-name: product-image;
}
浏览器会在推测预渲染阶段就把目标页面的 DOM 构建好;当用户点击时,先截图当前页面、激活隐藏 tab、匹配 view-transition-name、播放形变动画,整套动作在一个 vsync 帧内完成。用户看到的是"图片从卡片位置飞到详情页头图位置"的丝滑过渡,而不是白屏闪烁。这是 MPA 反攻 SPA 阵地的关键组合拳,也让 INP 主线程优化之外多了一条降低感知延迟的路径。
预渲染发生在隐藏的独立渲染进程中,常规 DevTools 面板无法直接查看。Chrome 提供了专门的调试入口:
- 打开目标页面,按 F12 或 Cmd+Option+I 打开 DevTools。
- 切换到 Application 面板,左侧 Background services 下点击 Speculative loads。
- 顶部有三个子标签:This page 显示当前页触发的规则;Speculations 列出每个候选 URL 及其状态(
Ready/Running/Failure);Rules 展示解析后的 JSON 规则。
- 点击任意 URL 可查看失败原因,例如
MojoBinderPolicy(某个 API 在预渲染中被禁用)、MemoryLimitExceeded、InvalidSchemeRedirect(跨域重定向)等。
常见失败码速查:PrerenderCancelled_UAChange 表示动态修改了 User-Agent;PrerenderCancelled_LoginRequired 表示目标页返回 401;PrerenderCancelled_Audible 表示后台页面尝试播放声音。这些都是浏览器主动杀掉预渲染进程以保护用户体验的信号。参考 Chrome DevTools 官方调试文档可获得完整失败码列表与 case-by-case 修复建议。
Safari 与 Firefox 不支持怎么办?
截至 2026 年 7 月,Safari 26 与 Firefox 128 均不支持 Speculation Rules API,非 Chromium 浏览器会静默忽略 <script type="speculationrules"> 标签。这不是灾难,你的站点在这些浏览器上会 fallback 到"普通导航"的表现,只是拿不到速度红利。推荐的降级策略:
- 基础层:为所有关键下一跳页面写传统
<link rel="prefetch" href="/checkout">,全平台兼容,覆盖到 Safari/Firefox 用户。
- 增强层:Chromium 浏览器额外加载 Speculation Rules,享受 prerender 级别的速度。
- PWA 层:在 Service Worker 里用
caches.addAll(['/checkout', '/product/...']) 提前把 HTML 灌进 Cache Storage,等同于跨浏览器的"手动 prefetch"。
数据佐证:一个典型电商站 Chromium 占比约 72%(Chrome 65% + Edge 5% + 三星浏览器 2%),把 72% 用户的 LCP 打到 300ms 已经能显著拉高整站的 Core Web Vitals 中位数。别忘了 Google 的 CrUX 数据是分位数指标,Chromium 用户的进步会直接体现在 p75 上。这也是为什么 Shopify、Ray-Ban、Cloudflare 都优先押注这项技术。
常见问题
Speculation Rules API 需要 HTTPS 吗?
是的。规范要求当前页面和目标页面都必须是安全上下文(HTTPS 或 localhost)。跨源预渲染额外要求目标响应包含 Supports-Loading-Mode: credentialed-prerender 响应头,否则会被浏览器拒绝激活。
预渲染会不会导致我的服务器被 CDN 回源压垮?
可能会。moderate 档同时最多 2 个 prerender,但一个页面可能有几十个链接,每次悬停都可能触发。生产环境建议:一是使用请求头 Sec-Purpose: prefetch;prerender 识别推测请求,在 CDN 层做限流或缓存打标;二是核心业务端点(下单、支付、登出)用 href_matches 显式排除。
Speculation Rules 与 Next.js/Nuxt 的路由预取冲突吗?
不冲突,但会重复工作。Next.js 15 已在 App Router 中原生集成 Speculation Rules(next/link 会自动注入规则),关闭其内置的 SPA 预取(prefetch=false)反而更省资源。Nuxt 4 需要手动通过 useHead 注入 <script type="speculationrules">。
如何测量 Speculation Rules 带来的真实性能提升?
使用 web-vitals 库上报 navigation.activationStart。预渲染激活的页面这个值会大于 0,其它字段(LCP、FCP、TTFB)都相对 activationStart 计算,因此可以对比"命中"与"未命中"两组会话的 CWV 差异。在 Chrome 用户体验报告(CrUX)中,2026 年 3 月起 navigation_types 维度已新增 prerender 与 prefetch 两个分类。
用户在浏览器里禁用了预加载还会生效吗?
不会。Chrome 的"预加载页面"设置(chrome://settings/performance)关闭、系统进入省流量模式、设备低电量或 CPU 负载过高时,浏览器会自动放弃所有推测加载。这也是 Speculation Rules 相对安全的一层保护,最坏情况就是不生效,不会伤害用户体验。