尽早建立网络连接以提升感知页面速度

了解 rel=preconnect 和 rel=dns-prefetch 资源提示以及如何使用它们。

在浏览器可以从服务器请求资源之前,它必须建立连接。建立安全连接涉及三个步骤

  • 查找域名并将其解析为 IP 地址。

  • 设置与服务器的连接。

  • 加密连接以确保安全。

在这些步骤中的每一步中,浏览器都会向服务器发送一条数据,服务器会发回响应。这种从源到目的地再返回的旅程称为往返

根据网络状况,单次往返可能需要相当长的时间。连接设置过程可能涉及最多三次往返 - 在未优化的情况下则更多。

提前处理好所有这些可以使应用程序感觉更快。这篇文章解释了如何使用两个资源提示来实现这一点:<link rel=preconnect><link rel=dns-prefetch>

使用 rel=preconnect 建立早期连接

现代浏览器尽力预测页面将需要哪些连接,但它们无法可靠地预测所有连接。好消息是,您可以给它们一个(资源 😉)提示。

rel=preconnect 添加到 <link> 会通知浏览器您的页面打算建立与另一个域的连接,并且您希望该过程尽快开始。资源将加载得更快,因为当浏览器请求它们时,设置过程已经完成。

资源提示之所以得名,是因为它们不是强制性指令。它们提供有关您希望发生的事情的信息,但最终由浏览器决定是否执行它们。建立和保持连接打开是一项繁重的工作,因此浏览器可能会选择忽略资源提示或根据情况部分执行它们。

告知浏览器您的意图就像在您的页面中添加 <link> 标记一样简单

<link rel="preconnect" href="https://example.com">

A diagram showing how the download doesn't start for a while after the connection is established.

通过尽早建立与重要的第三方来源的连接,您可以将加载时间加快 100–500 毫秒。这些数字看起来可能很小,但它们会影响用户感知网页性能的方式。

rel=preconnect 的用例

知道从哪里获取,但不知道获取什么

由于版本化的依赖关系,有时您最终会遇到这样一种情况:您知道您将从特定的 CDN 请求资源,但不知道它的确切路径。

A url of a script with the version name.
版本化 URL 的示例。

另一种常见情况是从图像 CDN 加载图像,其中图像的确切路径取决于媒体查询或用户浏览器上的运行时功能检查。

An image CDN URL with the parameters size=300x400 and quality=auto.
图像 CDN URL 的示例。

在这些情况下,如果您要获取的资源很重要,您希望通过预连接到服务器来尽可能节省时间。浏览器在您的页面请求之前不会下载该文件,但至少它可以提前处理连接方面的问题,从而使用户无需等待多次往返。

流媒体

您可能希望在连接阶段节省一些时间的另一个示例是,当从不同的来源流式传输媒体时,但不一定立即开始检索内容。

根据您的页面处理流式内容的方式,您可能希望等到您的脚本已加载并准备好处理流。预连接可帮助您在准备好开始获取后将等待时间缩短为单次往返。

如何实现 rel=preconnect

启动 preconnect 的一种方法是将 <link> 标记添加到文档的 <head> 中。

<head>
    <link rel="preconnect" href="https://example.com">
</head>

预连接仅对源域以外的域有效,因此您不应将其用于您的站点。

您还可以通过 Link HTTP 标头启动预连接

Link: <https://example.com/>; rel=preconnect

某些类型的资源(例如字体)以匿名模式加载。对于这些资源,您必须使用 preconnect 提示设置 crossorigin 属性

<link rel="preconnect" href="https://example.com/ComicSans" crossorigin>

如果您省略 crossorigin 属性,则浏览器仅执行 DNS 查找。

使用 rel=dns-prefetch 尽早解析域名

您通过名称记住站点,但服务器通过 IP 地址记住它们。这就是域名系统 (DNS) 存在的原因。浏览器使用 DNS 将站点名称转换为 IP 地址。此过程 - 域名解析 - 是建立连接的第一步。

如果页面需要连接到许多第三方域,则预连接所有这些域会适得其反。preconnect 提示最好仅用于最关键的连接。对于所有其余的连接,请使用 <link rel=dns-prefetch> 来节省第一步(DNS 查找)的时间,这通常需要大约 20–120 毫秒

DNS 解析的启动方式与 preconnect 类似:通过将 <link> 标记添加到文档的 <head> 中。

<link rel="dns-prefetch" href="http://example.com">

浏览器对 dns-prefetch 的支持preconnect 支持略有不同,因此 dns-prefetch 可以用作不支持 preconnect 的浏览器的后备方案。

操作
<link rel="preconnect" href="http://example.com">
<link rel="dns-prefetch" href="http://example.com">
要安全地实现后备技术,请使用单独的链接标记。
避免
<link rel="preconnect dns-prefetch" href="http://example.com">
在同一个 <link> 标记中实现 dns-prefetch 后备会导致 Safari 中的一个错误,其中 preconnect 被取消。

对最大内容ful Paint (LCP) 的影响

使用 dns-prefetchpreconnect 允许站点减少连接到另一个来源所需的时间。最终目标是将从另一个来源加载资源的时间尽可能缩短。

最大内容ful Paint (LCP) 而言,最好是资源可以立即被发现,因为 LCP 候选元素是用户体验的关键部分。fetchpriority 值为 "high" 的 LCP 资源可以通过向浏览器发出此资产的重要性信号来进一步改进这一点,以便它可以尽早获取它。

如果无法使 LCP 资产立即被发现,则 preload 链接(也具有 fetchpriority 值为 "high")仍然允许浏览器尽快加载资源。

如果这两个选项都不可用(因为确切的资源在页面加载的后期才会知道),您可以在跨域资源上使用 preconnect,以尽可能减少资源延迟发现的影响。

此外,就带宽使用而言,preconnectpreload 便宜,但仍然并非没有风险。与过多的 preload 提示一样,过多的 preconnect 提示在 TLS 证书方面仍然会消耗带宽。小心不要预连接到太多来源,因为这可能会导致带宽争用。

结论

当您知道您很快将从第三方域下载某些内容,但您不知道该资源的确切 URL 时,这两个资源提示有助于提高页面速度。示例包括分发 JavaScript 库、图像或字体的 CDN。请注意约束,仅对最重要的资源使用 preconnect,其余的依赖于 dns-prefetch,并始终衡量在现实世界中的影响。