尽早建立网络连接,以提升系统感知的网页速度

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

浏览器必须先建立连接,然后才能向服务器请求资源。建立安全连接需要完成以下三个步骤:

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

  • 设置与服务器的连接。

  • 为安全起见,请对连接进行加密。

在这些步骤中的每一个步骤中,浏览器都会向服务器发送一部分数据,然后服务器会发回响应。从起点到目的地再返回的这一行程称为往返

单次往返可能需要很长时间,具体取决于网络状况。连接设置过程最多可能涉及三次往返,在未优化的情况下,可能更多。

提前处理好上述事宜将使应用运行速度明显加快。本文介绍了如何使用两个资源提示 <link rel=preconnect><link rel=dns-prefetch> 实现此目的。

尽早与 rel=preconnect 建立联系

新型浏览器会尽力预测网页需要哪些连接,但无法可靠地预测所有连接。好消息是,您可以给他们提供一些(资源 😉?)提示。

<link> 添加 rel=preconnect 会告知浏览器您的网页打算与另一个网域建立连接,以及您希望尽快启动该过程。由于在浏览器请求资源时设置流程已完成,因此资源的加载速度会更快。

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

只需向您的页面添加一个 <link> 标记,便可告知浏览器您的意图:

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

一张示意图,显示了在连接建立后下载会暂时不开始的情况。

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

rel=preconnect 的用例

知道从哪里提取资源,但不知道提取的资源是什么

由于依赖项版本受到控制,您有时会遇到这种情况:您知道您将从特定 CDN 请求资源,但不知道其确切的路径。

包含版本名称的脚本的网址。
版本型网址示例。

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

包含参数 size=300x400 和 quality=auto 的图片 CDN 网址。
图片 CDN 网址示例。

在这些情况下,如果您要提取的资源很重要,您或许可以预连接到服务器,以尽可能地节省时间。除非您的网页请求,否则浏览器不会下载文件,但至少它可以提前处理连接,使用户无需等待若干往返。

流媒体

另一个您想在连接阶段节省时间但无需立即开始检索内容的示例是从不同的起点流式传输媒体。

根据您的页面处理流式传输内容的方式,您可能需要等待脚本加载完毕并准备好处理数据流。预连接可以在您准备好开始提取后,帮助您将等待时间缩减到单次往返。

如何实现 rel=preconnect

启动 preconnect 的方法之一是向文档的 <head> 添加 <link> 标记。

<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 类似:通过向文档的 <head> 添加 <link> 标记。

<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 中出现 bug,其中 preconnect 会被取消。

对 Largest Contentful Paint (LCP) 的影响

使用 dns-prefetchpreconnect 可让网站缩短连接到其他源所需的时间。最终目标是尽可能缩短从其他来源加载资源的时间。

Largest Contentful Paint (LCP) 而言,最好能立即发现资源,因为 LCP 候选项是用户体验的重要组成部分。为 LCP 资源设置 fetchpriority 值为 "high" 可以进一步改善这一点,因为这会向浏览器表明此资源对其的重要性,以便浏览器尽早提取该资源。

如果无法立即使 LCP 素材资源可被发现,preload 链接(fetchpriority 值也为 "high")仍可让浏览器尽快加载资源。

如果这两种方法都不可用(因为确切资源要到网页加载后期才能确定),您可以对跨源资源使用 preconnect,以尽可能减少资源晚发现的影响。

此外,从带宽用量方面来看,preconnect 的费用低于 preload,但仍存在风险。与过多的 preload 提示一样,过多的 preconnect 提示仍会消耗 TLS 证书的带宽。请注意不要预连接到太多源,因为这可能会导致带宽争用。

总结

如果您知道自己很快就会从第三方网域下载内容,但不知道该资源的确切网址,这两个资源提示有助于提高网页速度。例如,分发 JavaScript 库、图片或字体的 CDN。请注意限制,仅对最重要的资源使用 preconnect,对其余资源使用 dns-prefetch,并始终衡量实际影响。