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

了解 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">

显示在连接建立后的一段时间内未开始下载的示意图。

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

rel=preconnect 的用例

知道从何处获取,但不知道要提取什么

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

<ph type="x-smartling-placeholder">
</ph> 包含版本名称的脚本网址。
采用版本控制的网址示例。

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

<ph type="x-smartling-placeholder">
</ph> 参数为“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-prefetchpreconnect 支持略有不同,因此 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 被取消的错误。

对 Largest Contentful Paint (LCP) 的影响

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

Largest Contentful Paint (LCP) 而言,资源最好能被立即发现,因为 LCP 候选项是用户体验中的关键部分。如果 LCP 资源的 fetchpriority 值为 "high",则可进一步改进这一点,方法是向浏览器表明此资源的重要性,以便浏览器尽早提取。

即使无法让 LCP 资源立即被检测到,preload 链接(fetchpriority 值为 "high")仍允许浏览器尽快加载资源。

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

此外,就带宽使用而言,preconnectpreload 便宜,但其风险也并非如此。与过多的 preload 提示一样,在 TLS 证书方面,过多的 preconnect 提示仍会占用带宽。请注意不要预先连接到过多源,因为这可能会导致带宽争用。

总结

如果您知道自己很快会从第三方网域下载内容,但不知道相应资源的确切网址,那么这两种资源提示就有助于提高网页速度。例如,分发 JavaScript 库、图片或字体的 CDN。注意约束条件,仅对最重要的资源使用 preconnect,对于其余资源则依赖于 dns-prefetch,并始终衡量在现实世界中产生的影响。