借助“早期提示”利用服务器思考时间来加快页面加载速度

了解服务器如何向浏览器发送有关关键子资源的提示。

发布时间:2022 年 6 月 23 日,上次更新时间:2026 年 7 月 10 日

什么是 Early Hints?

网站随着时间的推移变得越来越复杂。因此,服务器需要执行一些重要的工作(例如访问数据库,或 CDN 访问源服务器)来生成所请求页面的 HTML,这并不罕见。遗憾的是,这种“服务器思考时间”会导致浏览器在开始呈现页面之前出现额外的延迟。实际上,在服务器准备响应期间,连接会处于空闲状态。

图片:显示了网页加载与加载其他资源之间 200 毫秒的服务器思考时间差。
如果没有 Early Hints:所有内容都会被服务器阻止,直到服务器确定如何响应主要资源。

Early Hints 是一种 HTTP 状态代码(103 Early Hints),用于在最终响应之前发送初步 HTTP 响应。这样一来,服务器在忙于生成主要资源时,就可以向浏览器发送有关关键子资源(例如页面的样式表、关键 JavaScript)或页面可能会使用的来源的提示。浏览器可以使用这些提示来预热连接并请求子资源,同时等待主要资源。换句话说,Early Hints 可帮助浏览器利用这种“服务器思考时间”提前完成一些工作,从而加快页面加载速度。

图片:显示了“早期提示”如何允许网页发送部分响应。
如果有 Early Hints:服务器可以在确定最终响应时提供包含资源提示的部分响应

在某些情况下,Largest Contentful Paint 的性能提升幅度可能从数百毫秒(如 Shopifyby Cloudflare 所观察到的)到一秒不等,如以下前后对比所示:

两个网站的比较。
使用 WebPageTest (Moto G4 - DSL) 在测试网站上进行 Early Hints 前后对比

如何使用 Early Hints

利用 Early Hints 的第一步是确定热门着陆页,即用户访问您的网站时通常会开始访问的页面。如果您有很多用户来自其他网站,则可能是首页或热门商品详情页面。这些入口点比其他页面更重要,原因是随着用户在您的网站上浏览,Early Hints 的实用性会降低(也就是说,浏览器更有可能在第二次或第三次后续导航时拥有所需的所有子资源)。留下良好的第一印象也始终是一个好主意!

现在您已获得此着陆页的优先列表,下一步是确定哪些来源或子资源适合作为 preconnectpreload 提示的候选对象。通常,这些来源和子资源对关键用户指标(例如 Largest Contentful PaintFirst Contentful Paint)的贡献最大。更具体地说,请查找呈现阻塞型子资源,例如同步 JavaScript、样式表,甚至是 Web 字体。同样,请查找托管对关键用户指标贡献很大的子资源的来源。

另请注意,如果您的主要资源已在使用 preconnectpreload,您可以考虑将这些来源或资源作为 Early Hints 的候选对象。如需了解详情,请参阅如何优化 LCP。不过,直接将 HTML 中的 preconnectpreload 指令复制到 Early Hints 可能不是最佳做法

在 HTML 中使用这些指令时,您通常需要 preconnectpreload 预加载扫描器在 HTML 中无法发现的资源,例如字体或背景图片,否则这些资源会被延迟发现。对于 Early Hints,您没有 HTML,因此您可能需要改为 preconnect 到关键网域或 preload 关键资源,这些资源可能原本会在 HTML 中被提前发现,例如预加载 main.cssapp.js。此外,并非所有浏览器都支持 Early Hints 的 preload,请参阅 浏览器支持

第二个验证步骤是最大限度地降低在可能已过时或不再被主要资源使用的资源或源上使用 Early Hints 的风险。例如,经常更新和版本控制的资源(例如 example.com/css/main.fa231e9c.css)可能不是最佳选择。请注意,此问题并非 Early Hints 特有,而是适用于任何可能存在的 preloadpreconnect。最好通过自动化或模板化来处理此类详细信息(例如,手动流程更有可能导致 preload 和使用资源的实际 HTML 标记之间出现哈希或版本网址不匹配的情况)。

例如,请考虑以下流程:

GET /main.html
Host: example.com
User-Agent: [....] Chrome/103.0.0.0 [...]

服务器预测需要 main.abcd100.css,并建议使用 Early Hints 预加载它:

103 Early Hints
Link: </main.abcd100.css>; rel=preload; as=style
[...]

片刻之后,系统会提供网页(包括链接的 CSS)。遗憾的是,此 CSS 资源经常更新,并且主要资源已比预测的 CSS 资源 (abcd100) 提前五个版本 (abcd105)。

200 OK
[...]
<HTML>
<head>
   <title>Example</title>
   <link rel="stylesheet" href="/main.abcd105.css">

一般来说,目标是资源和来源相当稳定,并且在很大程度上独立于主要资源的结果。如有必要,您可以考虑将关键资源拆分为两部分:一部分是稳定的,旨在与 Early Hints 搭配使用;另一部分是动态的,在浏览器收到主要资源后提取:

<html>
<head>
   <title>Example</title>
   <link rel="stylesheet" href="/main.css">
   <link rel="stylesheet" href="/experimental.3eab3290.css">

最后,在服务器端,查找已知支持 Early Hints 的浏览器发送的主要资源请求,并立即使用 103 Early Hints 进行响应。在 103 响应中,添加相关的预连接和预加载提示。主要资源准备就绪后,请继续发送常规响应(例如,如果成功,则为 200 OK)。为了实现向后兼容性,最好在最终响应中添加 Link HTTP 标头,甚至可以添加在生成主要资源时显现的关键资源(例如,如果您遵循“拆分为两部分”的建议,则为关键资源的动态部分)。如下所示:

GET /main.html
Host: example.com
User-Agent: [....] Chrome/103.0.0.0 [...]
103 Early Hints
Link: <https://fonts.google.com>; rel=preconnect
Link: </main.css>; rel=preload; as=style
Link: </common.js>; rel=preload; as=script

片刻之后:

200 OK
Content-Length: 7531
Content-Type: text/html; charset=UTF-8
Content-encoding: br
Link: <https://fonts.google.com>; rel=preconnect
Link: </main.css>; rel=preload; as=style
Link: </common.js>; rel=preload; as=script
Link: </experimental.3eab3290.css>; rel=preload; as=style
<HTML>
<head>
   <title>Example</title>
   <link rel="stylesheet" href="/main.css">
   <link rel="stylesheet" href="/experimental.3eab3290.css">
   <script src="/common.js"></script>
   <link rel="preconnect" href="https://fonts.googleapis.com">

浏览器支持

虽然所有主要浏览器都支持 103 Early Hints,但可以在 Early Hints 上发送的指令因浏览器而异:

预连接支持

Browser Support

  • Chrome: 103.
  • Edge: 103.
  • Firefox: 120.
  • Safari: 17.

预加载支持

Browser Support

  • Chrome: 103.
  • Edge: 103.
  • Firefox: 123.
  • Safari: not supported.

Chrome 开发者工具还支持 103 Early Hints,并且可以在文档资源中看到 Link 标头:

显示早期提示标头的“网络”面板
Early Hints Link 标头显示在 Chrome 开发者工具中。

请注意,如需使用 Early Hints 资源,Disable cache不得在 DevTools 中勾选“停用缓存”,因为 Early Hints 使用浏览器缓存。对于预加载的资源,发起者 将显示为 Early-hints大小 将显示为 (Disk cache)

显示“早期提示”发起方的“网络”面板
Early Hints 资源具有 early-hints 发起者,并且是从磁盘缓存加载的。

这还需要用于 HTTPS 测试的可信证书。

Firefox 在 DevTools 中没有明确的 103 Early Hints 支持作为发起者,但使用 Early Hints 加载的资源在已传输 列中显示为 cached,并且在点击时具有 X-Moz: early hint HTTP 请求标头。

服务器支持

以下是热门开源软件 HTTP 服务器软件对 Early Hints 的支持级别的简要总结:

更轻松地启用 Early Hints

如果您使用的是以下 CDN 或平台之一,则可能不需要手动实现 Early Hints。请参阅解决方案提供商的在线文档,了解其是否支持 Early Hints,或参阅此处的非详尽列表:

如何避免不支持 Early Hints 的客户端出现问题

100 范围内的信息性 HTTP 响应是 HTTP 标准的一部分,但一些较旧的客户端或机器人可能难以处理这些响应,因为在 103 Early Hints 发布之前,这些响应很少用于常规网页浏览。

仅在响应发送 sec-fetch-mode: navigate HTTP 请求标头的客户端时发出 103 Early Hints 应该仅针对了解等待后续响应的新客户端发送此类提示。此外,由于 Early Hints 仅在导航请求中受支持(请参阅 当前限制),因此还具有避免在其他请求中不必要地发送这些提示的额外优势。

此外,建议仅通过 HTTP/2 或 HTTP/3 连接发送 Early Hints,并且大多数浏览器仅接受通过这些协议发送的 Early Hints。

高级模式

如果您已将 Early Hints 完全应用于关键着陆页,并且发现自己正在寻找更多机会,那么您可能会对以下高级模式感兴趣。

对于在典型用户历程中第 n 个页面请求的访问者,您可能需要根据页面中较低且更深的内容调整 Early Hints 响应,换句话说,在低优先级资源上使用 Early Hints。 鉴于我们建议重点关注高优先级、呈现阻塞型子资源或来源,这听起来可能违反直觉。不过,当访问者浏览一段时间后,其浏览器很可能已拥有所有关键资源。从那时起,将注意力转向低优先级资源可能是有意义的。例如,这可能意味着使用 Early Hints 加载商品图片,或仅在不太常见的用户互动中需要的其他 JS/CSS。

当前限制

以下是 Chrome 中实现的 Early Hints 的限制:

  • 仅适用于导航请求(即顶级文档的主要资源)。
  • 仅支持 preconnectpreload(即不支持 prefetch)。
  • 如果 Early Hints 之后在最终响应中出现跨源重定向,则浏览器会丢弃使用 Early Hints 获取的资源和连接。
  • 使用 Early Hints 预加载的资源存储在 HTTP 缓存中,并由页面稍后从中检索。因此,只能使用 Early Hints 预加载可缓存的资源,否则资源将被双重提取(一次由 Early Hints 提取,另一次由文档提取)。在 Chrome 中,对于不受信任的 HTTPS 证书,HTTP 缓存处于停用状态(即使您继续加载页面也是如此)。
  • 使用 HTTP <link> 标头 可能不支持预加载响应式图片(使用 imagesrcsetimagesizesmedia),因为视口在创建文档之前未定义。它们最多会等到收到文档,从而抵消 103 Early Hints 的主要优势。

其他浏览器也有类似的限制,并且如前所述,有些浏览器进一步将 103 Early Hints 限制为preconnect

与 H2/Push 的关系

如果您熟悉已废弃的 HTTP2/Push 功能,您可能会想知道 Early Hints 有何不同。虽然 Early Hints 需要往返才能让浏览器开始提取关键子资源,但使用 HTTP2/Push 时,服务器可以开始推送子资源以及响应。虽然这听起来很棒,但会导致一个关键的结构性缺点:使用 HTTP2/Push 时,很难避免推送浏览器已有的子资源。这种“过度推送”效应导致网络带宽的使用效率降低,这严重阻碍了性能优势。总的来说,Chrome 数据显示,HTTP2/Push 实际上对整个网络的性能产生了负面影响。

相比之下,Early Hints 在实践中表现更好,因为它结合了发送初步响应的能力和提示,让浏览器负责提取或连接到它实际需要的内容。虽然 Early Hints 并未涵盖 HTTP2/Push 在理论上可以解决的所有用例,但我们认为 Early Hints 是加快导航速度的更实用的解决方案。

缩略图图片由Pierre Bamin提供。