性能 · API
Speculation Rules API
发布于 更新于
Speculation Rules API 让页面在 <script type="speculationrules"> 内的 JSON 块或 Speculation-Rules 响应头中声明浏览器应在用户导航之前预取或完整预渲染哪些 URL,于是下一次点击直接由内存应答。对文档而言它取代了 <link rel="prefetch"> 以及已废弃的 <link rel="prerender">(Chrome 63 起后者变成 NoState Prefetch),而且在生产环境中仅 Chromium 支持。
<script type="speculationrules">{ "prerender": [{ "where": { "href_matches": "/articles/*" }, "eagerness": "moderate" }], "prefetch": [{ "urls": ["/next.html"] }]}</script>Speculation-Rules: "/rules.json"该块由浏览器解析而不执行;不支持该类型的引擎会忽略它。Chrome 109 随同源预渲染一起发布了该 API,Chrome 121 加入 Speculation-Rules 头并让 source 成员变为可选;Safari 26.2 在「SpeculationRules prefetch」偏好之后实现了 prefetch 规则,Firefox 没有实现(BCD html.elements.script.type.speculationrules)。
| 成员 | 类型 | 含义 |
|---|---|---|
prefetch、prerender |
规则数组 | 动作。prefetch 下载响应;prerender 在隐藏标签页中加载并渲染页面,脚本也会执行。 |
urls |
字符串数组 | 列表规则:显式 URL,相对文档解析(带 "relative_to": "document" 时相对规则集解析)。 |
where |
object | 文档规则:对页面内链接的谓词,含 href_matches(URL 模式)、selector_matches(CSS 选择器)以及 and、or、not 组合子。 |
eagerness |
"immediate"、"eager"、"moderate"、"conservative" |
何时执行。immediate 在解析时;moderate 在悬停 200 ms 之后(触摸设备上为 pointerdown);conservative 在 pointerdown;eager 在 Chrome 143 之前与 immediate 行为相同,之后改为基于视口的启发式。列表规则默认 immediate,文档规则默认 conservative。 |
requires |
array | ["anonymous-client-ip-when-cross-origin"] 把跨源预取限定在私有预取代理上。 |
referrer_policy、tag、expects_no_vary_search、target_hint |
string | 推测请求的 referrer、在 DevTools 和 Sec-Speculation-Tags 头中显示的标签、No-Vary-Search 提示,以及预渲染的目标(_self 或 _blank)。 |
Chrome 限制并发的推测:immediate 规则 10 个预渲染和 50 个预取,eager、moderate 与 conservative 规则各 2 个,出现更新的候选时按先进先出替换(Prerender pages in Chrome,developer.chrome.com)。预取请求带 Sec-Purpose: prefetch;预渲染的文档看到 document.prerendering === true,并在激活时收到 prerenderingchange 事件。
无。
各引擎的支持情况
Section titled “各引擎的支持情况”Chromium 是唯一在生产环境中同时具备 prefetch 和 prerender 规则的引擎:Chrome 和 Edge 自 109 起,头形式自 121 起。Safari 26.2 只在启用「SpeculationRules prefetch」偏好时解析 prefetch 规则并忽略 prerender;Firefox 完全忽略该脚本类型(BCD html.elements.script.type.speculationrules)。不支持的引擎只是少了提前量,所以规则可以无条件发布。
示例覆盖一个规则集、预渲染页面需要的页面侧代码,以及兜底。
悬停时预渲染文章链接
Section titled “悬停时预渲染文章链接”moderate 热度的文档规则会预渲染指针停留 200 ms 的那篇文章,覆盖了多数点击,又不必渲染页面上的每个链接。
<script type="speculationrules">{ "prerender": [{ "where": { "and": [ { "href_matches": "/articles/*" }, { "not": { "selector_matches": ".no-prerender" } } ]}, "eagerness": "moderate" }]}</script>退出登录、一键操作之类绝不能预渲染的链接加上 no-prerender 类;预渲染的页面会运行脚本,加载时的副作用在用户决定访问之前就会发生。
把分析上报推迟到激活
Section titled “把分析上报推迟到激活”统计页面浏览的代码必须等预渲染页面变为可见,否则每个悬停过的链接都算一次访问。
function onVisible(callback) { if (document.prerendering) { document.addEventListener('prerenderingchange', callback, { once: true }); } else { callback(); // 未预渲染(或引擎不支持):页面已经可见 }}
onVisible(() => sendPageView(location.href));没有该 API 的引擎里 document.prerendering 为 undefined,else 分支把它当作普通的可见加载。
检测 API 并退回 prefetch
Section titled “检测 API 并退回 prefetch”HTMLScriptElement.supports('speculationrules') 是能力测试。兜底插入一个 <link rel="prefetch">,在 Firefox 和 Chromium 中为下一个文档预热 HTTP 缓存而不预渲染。
function speculate(url) { if (typeof HTMLScriptElement.supports !== 'undefined' && HTMLScriptElement.supports('speculationrules')) { const script = document.createElement('script'); script.type = 'speculationrules'; script.textContent = JSON.stringify({ prefetch: [{ urls: [url] }] }); document.head.append(script); return; } const link = document.createElement('link'); // 兜底:普通 prefetch,不预渲染 link.rel = 'prefetch'; link.href = url; document.head.append(link);}脚本添加的规则与静态规则计入同一限制;移除脚本元素会取消其待处理的推测并释放容量。
- Speculation Rules(wicg.github.io)
- Prerender pages in Chrome for instant page navigations(developer.chrome.com)
- Debug speculation rules(developer.chrome.com)
- 前进后退缓存(bfcache)
- 资源提示(preload 与 preconnect)
- View Transitions API
规范
| 规范 | 状态 |
|---|---|
| 无。 | |