推测规则预渲染,直到脚本源试用结束

发布时间:2026 年 1 月 23 日

Chrome 将从 Chrome 144 开始针对 Speculation Rules API 新增的 prerender until script 功能推出新的源试用。通过此源试用,网站可以面向真实用户试用此新功能。目的是对该功能进行实地测试,并向 Chrome 团队提供反馈,以帮助完善该功能并决定是否应将其添加到 Web 平台中。

此功能旨在解决什么问题?

借助 Speculation Rules API,可以在用户实际导航到网页之前开始加载网页。通过提前完成部分或全部工作,可以提高未来的网页加载速度。到目前为止,它允许两种类型的推测:预提取和预渲染。

预提取仅提取 HTML 文档。这样可以提前获取关键的第一项资源,从而在导航到网址时提升性能。它不会加载任何子资源(例如 CSS、JavaScript 或图片),也不会执行 JavaScript,因此浏览器在加载网页时可能仍需执行大量工作。

预渲染功能远不止于此。它会提取子资源,并开始呈现网页和执行 JavaScript,几乎就像在隐藏的后台标签页中打开网页一样。如果浏览器已完成呈现网页所需的所有工作,用户点击链接后即可立即进行导航。

使用预渲染选项可能会大幅提升性能,但会增加实现成本和资源成本。如果不仔细考虑,在用户实际导航到网页之前完全预渲染网页也可能会导致意想不到的副作用。例如,如果分析提供方未考虑推测,则分析可能会在用户导航之前触发,从而导致统计数据出现偏差。

使用预渲染的网站还必须注意不要向用户提供过时的网页。例如,如果您推测电子商务网站上的某个网页,然后向购物车中添加商品,接着加载之前推测的网页,那么如果该网站未采取额外措施来确保购物车数量得到更新,您可能会看到旧的购物车数量。

如果部分状态管理在服务器端进行,预提取也会遇到这些复杂情况,但对于预渲染来说,这通常是一个更大的问题。在更复杂的网站上使用预渲染可能会更复杂。

不过,我们从开发者那里了解到,他们已经通过预提取网页获得了性能提升,并希望进一步利用推测规则来获得更多好处。这时,脚本前预渲染就派上用场了。

什么是“脚本前预渲染”?

预渲染直到脚本是一种介于预提取和预渲染之间的新中间地带。它会预提取 HTML 文档(与预提取一样),然后开始渲染网页,包括提取所有子资源(与预渲染一样)。不过,最重要的是,浏览器会避免执行 <script> 元素(包括内嵌脚本和 src 脚本)。当遇到阻塞型 <script> 标记时,它会暂停解析器,并等待用户导航到相应网页,然后继续。与此同时,预加载扫描器可以继续运行,并提取网页所需的子资源,以便在网页可以继续加载时随时使用。

通过保留所有阻塞的 <script> 元素,可以避免大部分实现复杂性。与此同时,通过启动渲染流程并提取子资源,与预提取相比,性能有了巨大提升,可能几乎与完全预渲染一样。

在最佳情况下(网页中根本没有脚本),此选项将预渲染整个网页。或者,当网页的页脚中只有脚本元素或只有具有 asyncdefer 属性的脚本时,系统将完全预渲染该网页,而不会执行相应 JavaScript。即使在最糟糕的情况下(<head> 中存在阻塞脚本),网页渲染的开始,尤其是子资源的预提取,也应能大幅提升网页加载速度。

如何使用“脚本前预渲染”?

首先,启用该功能,然后预渲染,直到脚本以与其他 Speculation Rules API 选项相同的方式使用,并添加新的 prerender_until_script 键(请注意下划线,以使其成为有效的 JSON 键名)

此设置可与静态网址的列表规则搭配使用:

<script type="speculationrules">
{
  "prerender_until_script": [{
    "urls": ["next.html", "next2.html"]
  }]
}
</script>

它还可以与文档规则搭配使用,在文档规则中,要推测的网址以链接的形式显示在网页上:

<script type="speculationrules">
{
  "prerender_until_script": [{
    "where": { "href_matches": "/*" }
  }]
}
</script>

“Prerender until script”可与常规的 Speculation Rules API 选项搭配使用,包括各种急切程度值

由于 JavaScript 不会执行,因此无法读取 document.prerendering,也无法读取 prerenderingchange 事件。不过,activationStart 时间将不为零。

以下示例展示了如何部署上一个示例,并针对不支持 prerender_until_script 的浏览器回退到预提取:

<script type="speculationrules">
{
  "prerender_until_script": [{
    "where": { "href_matches": "/*" }
  }],
  "prefetch": [{
    "where": { "href_matches": "/*" }
  }]
}
</script>

Chrome 会毫无问题地处理此重复情况,并针对每种急切程度设置执行最合适的规则。

或者,您也可以将这些提示与不同的热切程度搭配使用,以热切预提取,然后升级为预渲染,直到脚本包含更多信号为止(如之前建议的那样,使用预提取/预渲染)

<script type="speculationrules">
{
  "prefetch": [{
    "where": { "href_matches": "/*" },
    "eagerness": "eager"
  }],
  "prerender_until_script": [{
    "where": { "href_matches": "/*" },
    "eagerness": "moderate"
  }]
}
</script>

请注意,您无法以这种方式将预渲染到脚本的预渲染升级为完全预渲染,但如果您希望 Chrome 支持这种模式,请为相应 bug 加星,以便我们了解您的需求。

所有 JavaScript 是否都已暂停?

否,只有 <script> 元素会导致解析器暂停。这意味着内嵌脚本处理程序(例如 onload)或 javascript: 网址不会导致暂停,并且可能会执行。

例如,这可以在导航到网页之前将 Hero image is now loaded 记录到控制台:

<img src="hero.jpg"
     onload="console.log('Hero image is now loaded!')"
     alt="Example Photo">

而如果使用 <script> 添加事件监听器,则在网页激活之前,不会将 Hero image is now loaded 记录到控制台:

<img src="hero.jpg" id="hero-image" alt="Example Photo">
<script>
  const heroImage = document.querySelector('#hero-image');
  if (heroImage.complete) {
        console.log('Hero image is now loaded');
  } else {
    heroImage.addEventListener('load',
      (event) => {
        console.log('Hero image is now loaded');
      }
    );
  }
</script>

这可能看起来不太直观,但在许多情况下(如上例中),立即采取行动可能更好,延迟采取行动可能会导致更多意想不到的并发症。

此外,大多数内嵌事件都需要用户操作(例如 onclickonhover),因此在用户可以与网页互动之前不会执行。

最后,之前的阻塞脚本会暂停解析器,从而阻止发现内嵌事件处理程序。因此,尽管是内嵌事件处理程序,但此代码在激活之前不会将消息加载到控制台:

<script>...</script>
<img src="hero.jpg"
     onload="console.log('Hero image is now loaded!')"
     alt="Example Photo">

这对于使用之前定义的代码的内嵌脚本处理程序尤其重要,这些处理程序将继续按预期运行:

<script>
imageLoadFunction() = {
   ...
}
</script>
<img src="hero.jpg" onload="imageLoadFunction" alt="Example Photo">

对于具有 asyncdefer 属性的脚本,情况如何?

具有 asyncdefer 属性的脚本会延迟到激活时执行,但不会阻止解析器继续处理网页的其余部分。脚本会下载,但直到用户导航到相应网页时才会执行。

如何启用“脚本前预渲染”?

“预渲染直到脚本”是我们正在开发的一项新选项,可能会发生变化,因此在先启用该选项以选择启用之前,无法使用该选项。

开发者可以使用 chrome://flags/#prerender-until-script Chrome 标志或 --enable-features=PrerenderUntilScript 命令行标志在本地启用该功能。

从 Chrome 144 开始,预渲染直至脚本也以源试用的形式提供。借助源试用,网站所有者可以在自己的网站上启用某项功能,以便真实用户使用该功能,而无需手动启用。这样,我们就可以衡量该功能对真实用户的影响,确保其按预期运行。

试用一下并分享您的反馈

我们非常期待 Speculation Rules API 的这一新增功能,并鼓励网站所有者试用一下。

GitHub 代码库中分享您对该提案的反馈。如需针对 Chrome 的实现提供反馈,请提交 Chromium bug