在 Chrome 中预渲染网页以实现即时网页导航

发布时间:2022 年 12 月 2 日;最后更新时间:2025 年 8 月 17 日

Browser Support

  • Chrome: 109.
  • Edge: 109.
  • Firefox: not supported.
  • Safari: not supported.

Source

Chrome 团队已恢复对用户可能访问的未来网页进行完整预渲染。

预渲染简史

过去,Chrome 支持 <link rel="prerender" href="/next-page"> 资源提示,但除了 Chrome 之外,它并未得到广泛支持,而且它并不是一个非常富有表现力的 API。

这种使用链接 rel=prerender 提示的旧版预渲染已被弃用,取而代之的是 NoState Prefetch,后者会提取未来页面所需的资源,但不会完全预渲染页面,也不会执行 JavaScript。NoState Prefetch 通过改进资源加载来帮助提高网页性能,但不会像完全预渲染那样实现即时加载网页。

Chrome 团队现已重新在 Chrome 中引入完整预渲染。为了避免与现有用法产生冲突,并为将来扩展预渲染功能留出空间,这种新的预渲染机制不会使用 <link rel="prerender"...> 语法,该语法仍用于 NoState Prefetch,但我们计划在未来某个时间点弃用它。

网页是如何预渲染的?

网页可以通过以下四种方式之一进行预渲染,所有这些方式都旨在加快导航速度:

  1. 当您在 Chrome 地址栏(也称为“多功能框”)中输入网址时,如果 Chrome 根据您之前的浏览记录高度确信您会访问该网页,则可能会自动预渲染该网页。
  2. 当您使用书签栏时,Chrome 可能会在您将指针悬停在某个书签按钮上时自动预渲染相应网页。
  3. 当您在 Chrome 地址栏中输入搜索字词时,如果搜索引擎指示 Chrome 这样做,Chrome 可能会自动预渲染搜索结果页面。
  4. 网站可以使用 Speculation Rules API 以程序化方式告知 Chrome 要预渲染哪些网页。此 API 会取代 <link rel="prerender"...> 之前的功能,并允许网站根据网页上的推测规则主动预渲染网页。这些内容可以静态地存在于网页上,也可以由 JavaScript 根据网页所有者的意愿动态注入。

在上述每种情况下,预渲染的行为都类似于在不可见的后台标签页中打开网页,然后通过将前台标签页替换为该预渲染的网页来“激活”该网页。如果网页在完全预渲染之前被激活,则其当前状态为“前台化”,并继续加载,这意味着您仍然可以获得良好的开端。

由于预渲染的网页是在隐藏状态下打开的,因此许多会导致侵入性行为(例如提示)的 API 在此状态下不会激活,而是会延迟到网页激活时再激活。在少数尚无法实现此功能的设备上,系统会取消预渲染。Chrome 团队正在努力将预渲染取消原因作为 API 公开,并增强开发者工具的功能,以便更轻松地识别此类边缘情况。

预渲染的影响

预渲染可实现近乎即时的网页加载,如以下视频所示:

预渲染的影响示例。

示例网站已经是一个快速网站,但即使如此,您也可以看到预渲染如何改善用户体验。因此,这也会直接影响网站的核心网页指标,实现接近于零的 LCP、减少 CLS(因为任何加载 CLS 都发生在初始视图之前),并改善 INP(因为加载应在用户互动之前完成)。

即使网页在完全加载之前就已激活,预先开始加载网页也应能改善加载体验。如果在预渲染仍在进行时激活链接,预渲染网页将移至主框架并继续加载。

不过,预渲染确实会占用额外的内存和网络带宽。请注意,不要过度预渲染,以免消耗过多的用户资源。仅在网页被访问的可能性较高时进行预渲染。

如需详细了解如何在分析中衡量实际效果影响,请参阅衡量效果部分。

查看 Chrome 的地址栏联想查询内容

对于第一种使用情形,您可以在 chrome://predictors 页面中查看 Chrome 对网址的预测:

Chrome 预测器页面经过过滤,可根据输入的文字显示低(灰色)、中(琥珀色)和高(绿色)预测。
Chrome 预测器页面。

绿线表示有足够的置信度来触发预渲染。在此示例中,输入“s”时,Chrome 会提供合理的置信度(琥珀色),但当您输入“sh”时,Chrome 会有足够的置信度来判断您几乎总是会前往 https://sheets.google.com

此屏幕截图是在相对较新的 Chrome 安装中拍摄的,并滤除了置信度为零的预测,但如果您查看自己的预测器,可能会看到更多条目,并且可能需要更多字符才能达到足够高的置信度。

这些预测器还会驱动您可能注意到的地址栏建议选项:

Chrome 地址栏“预输入”功能
地址栏“预输入”功能。

Chrome 会根据您的输入和选择不断更新其预测器。

  • 如果置信度高于 50%(以琥珀色显示),Chrome 会主动预先连接到相应网域,但不会预渲染网页。
  • 如果置信度高于 80%(以绿色显示),Chrome 将预渲染相应网址。

Speculation Rules API

对于 Speculation Rules API 的预渲染选项,Web 开发者可以在网页上插入 JSON 指令,以告知浏览器要预渲染哪些网址:

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

或者通过文档规则(自 Chrome 121 起提供),该规则会根据 href 选择器(基于 网址 模式 API)或 CSS 选择器预渲染文档中找到的链接:

<script type="speculationrules"> {   "prerender": [{     "where": {       "and": [         { "href_matches": "/*" },         { "not": {"href_matches": "/wp-admin"}},         { "not": {"href_matches": "/*\\?*(^|&)add-to-cart=*"}},         { "not": {"selector_matches": ".do-not-prerender"}},         { "not": {"selector_matches": "[rel~=nofollow]"}}       ]     }   }] } </script> 

Chrome 团队准备了一份 Speculation Rules Codelab,其中会引导您完成向网站添加 Speculation Rules 的过程。

Eagerness

Browser Support

  • Chrome: 121.
  • Edge: 121.
  • Firefox: not supported.
  • Safari: not supported.

Source

eagerness 设置用于指示推测应何时触发,这对于文档规则特别有用:

  • immediate:该设置用于尽快进行推测,即观察到推测规则后立即进行推测。
  • eager:此设置最初的行为与 immediate 完全相同,但从 Chrome 141 开始,它将更改为 5 毫秒悬停,并且计划在移动设备上进一步更改为简单的视口启发式
  • moderate:在桌面设备上,当您将光标悬停在链接上达到 200 毫秒时(或者发生 pointerdown 事件时,以更快者为准;在移动设备上没有 hover 事件),该设置会执行推测。在移动设备上,我们正在推出一项变更,以根据复杂的视口启发法来确定此值。
  • conservative:在发生指针点击或轻触时,该设置会执行推测。

list 规则的默认 eagernessimmediatemoderateconservative 选项可用于将 list 规则限制为用户与之互动的网址的特定列表。不过在许多情况下,采用具有适当 where 条件的 document 规则可能更为合适。

document 规则的默认 eagernessconservative。鉴于一个文档可能包含许多网址,因此在 document 规则中使用 immediateeager 时应谨慎(另请参阅下文中的 Chrome 限制部分)。

具体使用哪种 eagerness 设置取决于您的网站。对于轻量级静态网站,更积极地进行推测可能几乎没有成本,并且对用户有益。对于架构更复杂、网页有效内容更大的网站,您可能需要减少推测次数,直到从用户那里获得更多积极的意向信号,以限制浪费。

moderate 选项是一种中间方案,许多网站都可以从以下推测规则中受益,该规则会在将指针悬停在链接上 200 毫秒时或在 pointerdown 事件中预渲染链接,作为推测规则的基本但功能强大的实现:

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

预取

推测规则还可用于仅预提取网页,而无需进行完整的预渲染。这通常是实现预渲染的第一步:

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

Chrome 限制

Chrome 设有以下限制,以防止过度使用 Speculation Rules API:

渴望 预取 预渲染
immediate/eager 50 10
moderate/conservative 2 (FIFO) 2 (FIFO)
Chrome 中的推测限制。

moderateconservative 设置(取决于用户互动)以先进先出 (FIFO) 方式运行:达到限制后,新的推测将导致最旧的推测被取消并替换为较新的推测,以节省内存。已取消的推测可以再次触发(例如,通过再次将鼠标悬停在该链接上),这将导致系统重新推测该网址,从而推出最旧的推测。在这种情况下,之前的推测会缓存相应网址的 HTTP 缓存中的所有可缓存资源,因此进一步推测的成本应该会降低。因此,我们将限制设置为适中的阈值 2。静态列表规则不会因用户操作而触发,因此上限较高,因为浏览器无法知道哪些规则是必需的以及何时需要这些规则。

immediateeager 限制也是动态的,因此移除 list 网址脚本元素会通过取消这些移除的推测来创建容量。

Chrome 还将在某些情况下阻止使用推测,包括:

  • Save-Data
  • 节能模式(在启用且电池电量不足时)。
  • 内存限制。
  • 当“预加载网页”设置处于关闭状态时(该设置也会被 uBlock Origin 等 Chrome 扩展程序明确关闭)。
  • 在后台标签页中打开的网页。

Chrome 还会阻止在预渲染的网页上渲染跨源 iframe,直到网页激活。

所有这些条件旨在减少过度推测对用户造成的负面影响。

如何在网页上添加推测规则

推测规则可以静态包含在网页的 HTML 中,也可以通过 JavaScript 动态插入到网页中:

  • 静态包含的推测规则:例如,如果新闻媒体网站或博客的大部分用户经常会导航到最新文章,则可以预渲染该文章。或者,也可以使用包含 moderateconservative 的文档规则,在用户与链接互动时进行推测。
  • 动态插入的推测规则:这可能基于应用逻辑、针对用户进行个性化设置,或者基于其他启发式方法。

如果您倾向于根据悬停或点击链接等操作进行动态插入(许多库过去都使用 <link rel=prefetch> 实现了这一点),建议您查看文档规则,因为这些规则允许浏览器处理许多使用情形。

可以在主框架的 <head><body> 中添加推测规则。系统不会对子框架中的推测规则采取行动,并且只有在预渲染的页面被激活后,才会对其中的推测规则采取行动。

Speculation-Rules HTTP 标头

Browser Support

  • Chrome: 121.
  • Edge: 121.
  • Firefox: not supported.
  • Safari: not supported.

Source

还可以使用 Speculation-Rules HTTP 标头来传递推测规则,而不是直接将其包含在文档的 HTML 中。这样,CDN 可以更轻松地进行部署,而无需更改文档内容本身。

Speculation-Rules HTTP 标头随文档一起返回,并指向包含推测规则的 JSON 文件的位置:

Speculation-Rules: "/speculationrules.json" 

此资源必须使用正确的 MIME 类型,并且如果是跨源资源,则必须通过 CORS 检查。

Content-Type: application/speculationrules+json Access-Control-Allow-Origin: * 

如果您想使用相对网址,不妨在推测规则中添加 "relative_to": "document" 键。否则,相对网址将相对于推测规则 JSON 文件的网址。如果您需要选择一些(或全部)同源链接,此功能可能特别有用。

推测规则标记字段

Browser Support

  • Chrome: 136.
  • Edge: 136.
  • Firefox: not supported.
  • Safari: not supported.

Source

还可以在推测规则 JSON 语法中添加“标记”,无论是在单个规则级别:

{   "prefetch": [     "urls": ["next.html"],     "tag": "my-prefetch-rules"   ],   "prerender": [     "urls": ["next2.html"],     "tag": "my-prerender-rules"   ], } 

或者在规则集的所有推测规则的总体层级:

{   "tag": "my-rules",   "prefetch": [     "urls": ["next.html"]   ],   "prerender": [     "urls": ["next2.html"]   ], } 

然后,此标记会反映在 Sec-Speculation-Tags HTTP 标头中,可用于在服务器端过滤推测规则。如果推测符合多条规则,Sec-Speculation-Tags HTTP 标头可以包含多个标记,如以下示例所示:

Sec-Speculation-Tags: null Sec-Speculation-Tags: null, "cdn-prefetch" Sec-Speculation-Tags: "my-prefetch-rules" Sec-Speculation-Tags: "my-prefetch-rules", "my-rules", "cdn-prefetch" 

有些 CDN 会自动注入推测规则,但会阻止对非边缘缓存网页的推测,以避免此功能导致源服务器使用量增加。标记允许它们识别由其默认规则集启动的推测,但仍允许网站添加的任何规则传递到来源。

标记在工具中也可能很有用,例如我们正考虑向开发者工具添加标记

推测规则 target_hint 字段

Browser Support

  • Chrome: 138.
  • Edge: 138.
  • Firefox: not supported.
  • Safari: not supported.

Source

推测规则还可以包含 target_hint 字段,其中包含有效的浏览上下文名称或关键字,用于指明网页预期在何处激活预渲染的内容:

<script type=speculationrules> {   "prerender": [{     "target_hint": "_blank",     "urls": ["next.html"]   }] } </script> 

此提示允许处理 target="_blank" 链接的预渲染推测:

<a target="_blank" href="next.html">Open this link in a new tab</a> 

目前,Chrome 中仅支持 "target_hint": "_blank""target_hint": "_self"(如果未指定,则为默认值),并且仅支持预渲染,不支持预提取。

target_hint 仅适用于 urls 推测规则,因为对于文档规则,target 可从链接本身获知。

推测规则和 SPA

推测规则仅支持由浏览器管理的全页导航,不支持单页应用 (SPA) 或应用 shell 页面。这些架构不使用文档提取,而是对数据或网页进行 API 或部分提取,然后对提取的数据或网页进行处理并显示在当前网页中。应用可以在推测规则之外预提取这些所谓的“软导航”所需的数据,但无法预渲染这些数据。

Speculation Rules 可用于从上一个网页预渲染应用本身。这有助于抵消某些 SPA 的部分额外初始加载费用。不过,应用内的路线更改无法预渲染。

调试推测规则

如需了解可帮助您查看和调试此新 API 的 Chrome DevTools 新功能,请参阅有关调试推测规则的专门博文

多个推测规则

您还可以向同一网页添加多条推测规则,这些规则会附加到现有规则中。因此,以下不同的方式都会导致 one.htmltwo.html 预渲染:

网址列表

<script type="speculationrules"> {   "prerender": [     {       "urls": ["one.html", "two.html"]     }   ] } </script> 

多个 speculationrules 脚本

<script type="speculationrules"> {   "prerender": [     {       "urls": ["one.html"]     }   ] } </script> <script type="speculationrules"> {   "prerender": [     {       "urls": ["two.html"]     }   ] } </script> 

一个 speculationrules 中包含多个列表

<script type="speculationrules"> {   "prerender": [     {       "urls": ["one.html"]     },     {       "urls": ["two.html"]     }   ] } </script> 

Browser Support

  • Chrome: 127.
  • Edge: 127.
  • Firefox: not supported.
  • Safari: not supported.

Source

在预提取或预渲染网页时,某些网址参数(技术上称为搜索参数)对于服务器实际传送的网页可能并不重要,仅供客户端 JavaScript 使用。

例如,Google Analytics 使用 UTM 参数来衡量广告系列效果,但通常不会导致服务器传送不同的网页。这意味着 page1.html?utm_content=123page1.html?utm_content=456 将从服务器传送同一网页,因此可以从缓存中重复使用同一网页。

同样,应用可能会使用仅在客户端处理的其他网址参数。

No-Vary-Search 提案允许服务器指定不会导致所交付资源发生变化的参数,因此允许浏览器重复使用之前缓存的文档版本,这些版本仅在这些参数上有所不同。Chrome(以及基于 Chromium 的浏览器)支持预提取和预渲染的导航推测。

推测规则支持使用 expects_no_vary_search 来指明预期返回 No-Vary-Search HTTP 标头的位置。这样做有助于进一步避免在看到回答之前进行不必要的下载。

<script type="speculationrules"> {   "prefetch": [{     "urls": ["/products"],     "expects_no_vary_search": "params=(\"id\")"   }] } </script>  <a href="/products?id=123">Product 123</a> <a href="/products?id=124">Product 124</a> 

在此示例中,商品 ID 123124/products 初始网页 HTML 相同。不过,网页内容最终会因客户端渲染而有所不同,因为客户端渲染会使用 JavaScript 通过 id 搜索参数提取商品数据。因此,我们会预提取该网址,并且该网址应返回一个 No-Vary-Search HTTP 标头,表明该网页可用于任何 id 搜索参数。

不过,如果用户在预提取完成之前点击了任何链接,浏览器可能尚未收到 /products 网页。在这种情况下,浏览器不知道响应是否会包含 No-Vary-Search HTTP 标头。然后,浏览器可以选择再次提取链接,也可以等待预提取完成,以查看其中是否包含 No-Vary-Search HTTP 标头。expects_no_vary_search 设置可让浏览器知道网页响应应包含 No-Vary-Search HTTP 标头,并等待该预提取完成。

您还可以向 expects_no_vary_search 添加多个参数,只需使用空格分隔它们即可(因为 No-Vary-Search 是 HTTP 结构化标头):

    "expects_no_vary_search": "params=(\"param1\" \"param2\" \"param3\")" 

推测规则限制和未来增强功能

推测规则仅限于在同一标签页中打开的网页,但我们正在努力减少这一限制

默认情况下,推测仅限于同源页面。推测相同网站的跨源网页(例如,https://a.example.com 可以预渲染 https://b.example.com 上的网页)。若要使用此功能,推测的网页(在本例中为 https://b.example.com)需要通过添加 Supports-Loading-Mode: credentialed-prerender HTTP 标头来选择启用,否则 Chrome 将取消推测。

未来的版本可能还会允许为非同网站、跨源网页进行预渲染,前提是预渲染的网页没有 Cookie,并且通过类似的 Supports-Loading-Mode: uncredentialed-prerender HTTP 标头选择启用预渲染。

推测规则已支持跨源预提取,但同样仅在不存在跨源网域的 Cookie 时才支持。如果用户之前访问过相应网站,并且存在相关 Cookie,则系统不会使用推测,并且会在开发者工具中显示失败。

鉴于这些当前限制,一种可以尽可能改善用户体验的模式是预渲染同源网址并尝试预提取跨源网址,无论这些网址是内部链接还是外部链接:

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

默认情况下,限制跨源链接的跨源推测对于安全性而言是必要的。对于跨源目的地,它比 <link rel="prefetch"> 有所改进,前者也不会发送 Cookie,但仍会尝试预提取,这要么会导致预提取浪费,需要重新发送,要么更糟糕的是,会导致页面加载不正确。

检测 Speculation Rules API 支持

您可以使用标准 HTML 检查来检测 Speculation Rules API 支持:

if (HTMLScriptElement.supports && HTMLScriptElement.supports('speculationrules')) {   console.log('Your browser supports the Speculation Rules API.'); } 

通过 JavaScript 动态添加推测规则

以下示例展示了如何使用 JavaScript 添加 prerender 推测规则:

if (HTMLScriptElement.supports &&     HTMLScriptElement.supports('speculationrules')) {   const specScript = document.createElement('script');   specScript.type = 'speculationrules';   specRules = {     prerender: [       {         urls: ['/next.html'],       },     ],   };   specScript.textContent = JSON.stringify(specRules);   console.log('added speculation rules to: next.html');   document.body.append(specScript); } 

您可以在此预渲染演示页面上查看使用 JavaScript 插入的 Speculation Rules API 预渲染演示。

使用 innerHTML<script type = "speculationrules"> 元素直接插入 DOM 中不会注册推测规则,这是出于安全考虑,因此必须按之前的示例所示添加该元素。不过,使用 innerHTML 动态插入的包含新链接的内容会被网页上的现有规则捕获。

同样,直接在 Chrome DevTools 中编辑元素面板以添加 <script type = "speculationrules"> 元素不会注册推测规则,而必须从控制台运行脚本才能将此元素动态添加到 DOM 以插入规则。

通过跟踪代码管理器添加推测规则

如需使用 Google 跟踪代码管理器 (GTM) 等代码管理工具添加推测规则,必须通过 JavaScript 插入这些规则,而不是直接通过 GTM 添加 <script type = "speculationrules"> 元素,原因与之前所述相同:

Google 跟踪代码管理器中的自定义 HTML 代码配置
通过 Google 跟踪代码管理器添加推测规则。

请注意,此示例使用 var,因为 GTM 不支持 const

取消推测规则

移除推测规则会导致预渲染被取消。不过,在发生这种情况时,资源可能已经花费在启动预渲染上,因此建议不要预渲染可能需要取消预渲染的页面。另一方面,缓存的资源仍可重复使用,因此取消可能不会完全浪费,并且可能仍有助于未来的推测和导航。

Browser Support

  • Chrome: 138.
  • Edge: 138.
  • Firefox: not supported.
  • Safari: not supported.

Source

您还可以使用带有 prefetchCacheprerenderCache 指令的 Clear-Site-Data HTTP 标头来取消推测。

当服务器上的状态发生变化时,此功能非常有用。例如,在调用“添加到购物车”API 或登录/退出 API 时。

理想情况下,这些状态更新会使用 Broadcast Channel API 等 API 传播到预渲染的网页,但在无法实现此目的或此类逻辑实现之前,取消推测会更简单。

推测规则和内容安全政策

由于推测规则使用 <script> 元素,因此即使它们仅包含 JSON,如果网站使用 script-src Content-Security-Policy,也需要将其包含在其中(使用哈希或随机数)。

可向 script-src 添加新的 inline-speculation-rules,以支持从哈希或含 nonce 的脚本注入的 <script type="speculationrules"> 元素。此功能不支持初始 HTML 中包含的规则,因此对于使用严格 CSP 的网站,需要通过 JavaScript 注入规则。

检测并停用预渲染

预渲染通常能为用户带来良好的体验,因为它可以快速(通常是即时)呈现网页。这不仅有利于用户,也有利于网站所有者,因为预渲染的网页可提供更好的用户体验,而这在其他情况下可能难以实现。

不过,在某些情况下,您可能不希望预渲染网页,例如当网页根据初始请求或根据在网页上执行的 JavaScript 更改状态时。

在 Chrome 中启用和停用预渲染

预渲染仅适用于在 chrome://settings/performance/ 中启用了“预加载网页”设置的 Chrome 用户。此外,在低内存设备上,或者当操作系统处于“节省流量”模式或“节能”模式时,预渲染也会停用。请参阅 Chrome 限制部分。

检测并停用预渲染服务器端

预渲染的网页将随 Sec-Purpose HTTP 标头一起发送:

Sec-Purpose: prefetch;prerender 

使用 Speculation Rules API 预提取的网页会将此标头设置为 prefetch

Sec-Purpose: prefetch 

服务器可以根据此标头进行响应,以记录推测请求、返回不同的内容或阻止预渲染。如果返回非成功的最终响应代码(即重定向后不在 200-299 范围内),则不会预渲染网页,并且任何预提取的网页都会被舍弃。另请注意,204 和 205 响应不适用于预渲染,但适用于预提取。

如果您不希望预渲染特定网页,最好的方法是返回非 2XX 响应代码(例如 503),以确保不会发生预渲染。不过,为了提供最佳体验,建议改为允许预渲染,但使用 JavaScript 延迟任何仅在实际查看网页时才应发生的操作。

在 JavaScript 中检测预渲染

在网页预渲染时,document.prerendering API 将返回 true。网页可以使用此属性来防止或延迟预渲染期间的某些活动,直到网页实际激活为止。

预渲染的文档激活后,PerformanceNavigationTimingactivationStart 也会设置为一个非零时间,表示预渲染开始与文档实际激活之间的时间。

您可以编写一个函数来检查预渲染和预渲染的网页,如下所示:

function pagePrerendered() {   return (     document.prerendering ||     self.performance?.getEntriesByType?.('navigation')[0]?.activationStart > 0   ); } 

如需轻松查看网页是否已预渲染(完全或部分),请在网页激活后打开开发者工具,然后在控制台中输入 performance.getEntriesByType('navigation')[0].activationStart。如果返回非零值,则表示网页已预渲染:

Chrome 开发者工具中的控制台,其中显示了正数的 activationStart,表明网页已预渲染
在控制台中测试预渲染。

当用户查看网页而激活网页时,系统会在 document 上调度 prerenderingchange 事件,然后可以使用该事件来启用之前会在网页加载时默认启动的活动,但您希望延迟到用户实际查看网页时再启动这些活动。

借助这些 API,前端 JavaScript 可以检测预渲染的网页并采取适当的行动。

对分析的影响

分析用于衡量网站使用情况,例如使用 Google Analytics 来衡量网页浏览量和事件。或者,您也可以使用实时用户监控 (RUM) 来衡量网页的性能指标。

只有当用户很有可能会加载某个网页时,才应预渲染该网页。因此,只有在概率非常高(超过 80% 的时间)的情况下,Chrome 地址栏预渲染选项才会生效。

不过,特别是使用 Speculation Rules API 时,预渲染的网页可能会影响分析,网站所有者可能需要添加额外的代码,以便仅在激活时为预渲染的网页启用分析,因为并非所有分析提供商都可能默认执行此操作。

这可以通过使用 Promise 来实现,如果文档正在预渲染,则该 Promise 会等待 prerenderingchange 事件;如果文档现在正在渲染,则该 Promise 会立即解析:

// Set up a promise for when the page is activated, // which is needed for prerendered pages. const whenActivated = new Promise((resolve) => {   if (document.prerendering) {     document.addEventListener('prerenderingchange', resolve, {once: true});   } else {     resolve();   } });  async function initAnalytics() {   await whenActivated;   // Initialise your analytics }  initAnalytics(); 

另一种方法是将分析活动延迟到页面首次变为可见时,这样既可以涵盖预渲染情况,也可以涵盖在后台打开标签页(例如,通过右键点击并选择“在新标签页中打开”)的情况:

// Set up a promise for when the page is first made visible const whenFirstVisible = new Promise((resolve) => {   if (document.hidden) {     document.addEventListener('visibilitychange', resolve, {once: true});   } else {     resolve();   } });  async function initAnalytics() {   await whenFirstVisible;   // Initialise your analytics }  initAnalytics(); 

虽然这对于分析和类似的使用情形可能很有意义,但在其他情况下,您可能希望为这些情形加载更多内容,因此可能希望使用 document.prerenderingprerenderingchange 来专门定位预渲染页面。

在预渲染期间延迟加载其他内容

之前讨论的相同 API 可用于在预渲染阶段保留其他内容。这可以是您在预渲染阶段不希望运行的特定 JavaScript 部分或整个脚本元素。

例如,假设有以下脚本:

<script src="https://example.com/app/script.js" async></script> 

您可以将其更改为动态插入的脚本元素,该元素仅根据之前的 whenActivated 函数进行插入:

async function addScript(scriptUrl) {   await whenActivated;   const script = document.createElement('script');   script.src = 'scriptUrl';   document.body.appendChild(script); }  addScript('https://example.com/app/script.js'); 

这有助于延迟包含 Google Analytics 的各个脚本,或根据访问期间可能发生变化的状态或其他变量来呈现内容。例如,建议、登录状态或购物车图标可能会被延迟显示,以确保呈现最新信息。

虽然使用预渲染时这种情况可能更频繁地发生,但这些条件也适用于之前提到的在后台标签页中加载的网页(因此可以使用 whenFirstVisible 函数代替 whenActivated)。

在许多情况下,最好还在一般 visibilitychange 更改时检查状态,例如,当返回到已在后台运行的页面时,任何购物车计数器都应更新为购物车中的最新商品数量。因此,这不是预渲染特有的问题,而是预渲染只是让现有问题更加明显。

Chrome 缓解了手动封装脚本或函数需求的一种方式是,如前所述,某些 API 会被延迟,并且第三方 iframe 不会呈现,因此只有位于此 iframe 之上的内容才需要手动延迟。

衡量效果

对于衡量性能指标,分析应考虑是根据激活时间(而非浏览器 API 将报告的网页加载时间)来衡量这些指标是否更合适。

对于通过 Chrome 用户体验报告由 Chrome 测量的核心网页指标,这些指标旨在衡量用户体验。因此,这些指标是根据激活时间来衡量的。这通常会使 LCP 缩短到 0 秒,表明这是改进核心网页指标的好方法。

自版本 3.1.0 起,web-vitals已更新,可按照 Chrome 衡量 Core Web Vitals 的方式处理预渲染导航。如果网页已完全或部分预渲染,此版本还会通过 Metric.navigationType 属性为这些指标标记预渲染的导航。

衡量预渲染

如果 PerformanceNavigationTiming 的非零 activationStart 条目存在,则表示网页已预呈现。然后,可以使用自定义维度记录此信息,或者在记录网页浏览时使用类似方法(例如使用前面介绍的 pagePrerendered 函数)记录此信息:

// Set Custom Dimension for Prerender status gtag('set', { 'dimension1': pagePrerendered() }); // Initialise GA - including sending page view by default gtag('config', 'G-12345678-1'); 

这样,您的分析数据就可以显示预渲染的导航次数与其他类型的导航次数相比如何,还可以将任何性能指标或业务指标与这些不同的导航类型相关联。网页加载速度越快,用户越满意,这通常会对业务指标产生实际影响,正如我们的研究案例所示。

在衡量预渲染页面对即时导航的业务影响时,您可以决定是否值得投入更多精力来使用此技术,以允许预渲染更多导航,或者调查页面未被预渲染的原因。

衡量命中率

除了衡量预渲染后访问的网页的影响之外,还应衡量预渲染后被访问的网页。这可能意味着您预渲染的内容过多,导致用户宝贵的资源被白白浪费。

这可以通过在插入推测规则时(在通过 HTMLScriptElement.supports('speculationrules') 检查浏览器是否支持预渲染之后)触发一个分析事件来衡量,以表明已请求预渲染。(请注意,即使请求了预渲染,也不表示已开始或完成预渲染,因为如前所述,预渲染只是对浏览器的提示,浏览器可能会根据用户设置、当前内存用量或其他启发式方法选择不预渲染网页。)

然后,您可以将这些事件的数量与实际预渲染网页浏览量进行比较。或者,如果这样更便于比较,也可以在激活时触发另一个事件。

然后,您可以通过查看这两个数字之间的差值来大致了解“成功命中率”。对于使用 Speculation Rules API 预渲染网页的网页,您可以适当调整规则,以确保保持较高的命中率,从而在消耗用户资源来帮助用户与不必要地消耗用户资源之间保持平衡。

请注意,由于地址栏预渲染,可能正在进行一些预渲染,而不仅仅是您的推测规则。如果您想区分这些情况,可以检查 document.referrer(对于包括预渲染地址栏导航在内的地址栏导航,此属性将为空白)。

请务必查看没有预渲染的网页,因为这可能表明这些网页不符合预渲染条件,即使是从地址栏也是如此。这可能意味着您无法从这项性能增强功能中受益。Chrome 团队正考虑添加额外的工具来测试预渲染资格,可能类似于 bfcache 测试工具,还可能会添加一个 API 来公开预渲染失败的原因。

对扩展服务的影响

请参阅有关 Chrome 扩展程序:扩展 API 以支持即时导航的专门博文,其中详细介绍了扩展程序作者可能需要考虑的一些其他事项(针对预渲染的网页)。

反馈

Chrome 团队正在积极开发预渲染功能,并计划扩大 Chrome 108 版本中已提供的功能范围。我们欢迎您通过 GitHub 代码库或使用问题跟踪器提供任何反馈,并期待听到和分享有关这项令人兴奋的新 API 的案例研究。

致谢

缩略图图片由 Unsplash 用户 Marc-Olivier Jodoin 提供