# Speculation Rules API：预取与预渲染可能的下一页

> 一段 speculationrules 类型的 script JSON 块如何告诉浏览器在用户导航前预取或预渲染哪些 URL，控制时机的 eagerness 级别，以及为何它的支持以 Chromium 为主——Safari 仅实验性支持 prefetch，Firefox 完全未实现。

**一句话：** Speculation Rules API 让页面在一段 `speculationrules` 类型的 JSON
script 块中声明浏览器应当预取或预渲染哪些 URL；根据 MDN，被预渲染的导航可以感觉近乎
瞬时完成，而预取只是提前下载响应体，让最终的渲染更快。

## 声明规则

一段 speculation rules 块在 `prerender` 或 `prefetch` 动作下列出 URL（或一个文档级
匹配模式）：

```html
<script type="speculationrules">
{
  "prerender": [
    {
      "urls": ["/next-page.html"]
    }
  ]
}
</script>
```

根据 Chrome for Developers，当浏览器预渲染 `/next-page.html` 后，导航到该 URL 会直接
使用已经渲染好的页面提供服务，而不是发起一次全新的加载。

## Eagerness（急切程度）

根据 Chrome for Developers，每条规则都可以设置 `eagerness` 为 `"immediate"`、
`"eager"`、`"moderate"` 或 `"conservative"`，用以控制浏览器多快对其采取行动。若规则
未另行指定，列表（`"urls"`）规则默认是 `"immediate"`，文档（`"where"`）规则默认是
`"conservative"`：

```html
<script type="speculationrules">
{
  "prerender": [
    {
      "where": { "href_matches": "/articles/*" },
      "eagerness": "moderate"
    }
  ]
}
</script>
```

根据 Chrome for Developers，在桌面端 `"moderate"` 会在指针悬停在匹配链接上约 200ms
后触发预测（若更早发生 `pointerdown` 则以此为准）；在移动端则改用视口启发式方法，而
非悬停或 `pointerdown`。`"conservative"` 会等到指针/触摸按下才触发——这是资源消耗
最低、最保守的选项。

## 支持情况

根据 MDN 的兼容性数据，Speculation Rules API 主要是基于 Chromium 的特性（Chrome、
Edge，以及 Opera、三星 Internet 等其他基于 Chromium 的浏览器）；Firefox 未实现它，
而 Safari 26.2 仅在实验性偏好设置开启时支持 `prefetch` 规则，不支持 `prerender`。
在不支持的浏览器中，一段 `speculationrules` 类型的 `<script>` 块只是被忽略的惰性标记。

## 特性检测与回退

```js
function supportsSpeculationRules() {
  return (
    typeof HTMLScriptElement.supports !== 'undefined' &&
    HTMLScriptElement.supports('speculationrules')
  );
}

if (supportsSpeculationRules()) {
  const script = document.createElement('script');
  script.type = 'speculationrules';
  script.textContent = JSON.stringify({
    prefetch: [{ urls: ['/next-page.html'] }],
  });
  document.head.append(script);
} else {
  // 不受支持：回退到更古老、浏览器支持范围更广的 <link rel="prefetch">，
  // 依然能为下一次导航预热缓存。
  const link = document.createElement('link');
  link.rel = 'prefetch';
  link.href = '/next-page.html';
  document.head.append(link);
}
```

## 实用清单

- [ ] 在依赖它之前先用 `HTMLScriptElement.supports('speculationrules')` 做特性检测，
      并为其他引擎提供 `<link rel="prefetch">` 回退。
- [ ] 对于你只是中等把握用户会访问的页面，优先使用 `prefetch` 而非
      `prerender`——根据 MDN，未被使用的预取同样会浪费网络带宽和缓存内存，只是其
      前期开销比未被使用的预渲染更小。
- [ ] 不要把每条规则都默认设为 `"immediate"`——根据 Chrome for Developers，
      immediate/eager 规则会让浏览器同时在内存中保留数量有限的预取/预渲染页面。
- [ ] 记住这个 API 在 Firefox 上没有任何效果，在 Safari 上也只有有限的实验性
      `prefetch` 支持；不要构建依赖它才能在这些浏览器上正常工作的功能。
- [ ] 重新核对每种规则类型的默认 eagerness——列表规则默认 `"immediate"`，文档规则
      默认 `"conservative"`。

## 相关参考

- [导航预加载](/zh/reference/performance/navigation-preload/)
- [核心网页指标](/zh/reference/performance/core-web-vitals/) —— 根据 Chrome for
  Developers，预渲染可以改善 LCP、CLS 与 INP。