了解 rel=preconnect 和 rel=dns-prefetch 资源提示及其使用方式。
浏览器必须先建立连接,然后才能从服务器请求资源。建立安全连接需要完成三个步骤:
查找域名并将其解析为 IP 地址。
设置与服务器的连接。
加密连接以确保安全。
在每个步骤中,浏览器都会向服务器发送一部分数据,而服务器会发回响应。从出发地到目的地再返回的整个行程称为“往返行程”。
根据网络条件,一次往返可能需要相当长的时间。连接设置过程可能涉及最多 3 个往返,在未优化的情况下甚至更多。
提前处理好所有这些问题,可让应用感觉快得多。本文将介绍如何使用两种资源提示(<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 加载图片,其中图片的具体路径取决于用户浏览器上的媒体查询或运行时功能检查。
在这些情况下,如果您要提取的资源很重要,则需要通过预先连接到服务器来尽可能节省时间。浏览器不会下载该文件,直到您的网页请求该文件为止,但至少可以提前处理连接方面的问题,从而避免用户等待多次往返。
流媒体
另一个示例是,您可能希望在连接阶段节省一些时间,但不一定立即开始检索内容,例如从其他来源流式传输媒体时。
根据网页处理流式内容的方式,您可能需要等到脚本加载完毕并准备好处理数据流后,再开始处理数据流。预连接有助于您在准备开始提取时将等待时间缩短为一次往返。
如何实现 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 类似:通过向文档的 <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 中出现 preconnect 被取消的 bug。
对 Largest Contentful Paint (LCP) 的影响
使用 dns-prefetch 和 preconnect 可让网站缩短连接到其他来源所需的时间。最终目标是尽可能缩短从其他来源加载资源的时间。
就Largest Contentful Paint (LCP) 而言,资源最好能立即被发现,因为 LCP 候选元素是用户体验的关键部分。LCP 资源上的 fetchpriority 值 "high" 可以通过向浏览器表明此资源的重要性来进一步改进此指标,以便浏览器可以提前提取该资源。
如果无法使 LCP 资源立即可发现,preload 链接(同样具有 "high" 的 fetchpriority 值)仍允许浏览器尽快加载资源。
如果这两个选项均不可用(因为在网页加载完成之前无法确切知道资源),您可以在跨源资源上使用 preconnect,以尽可能减少资源延迟发现的影响。
此外,就带宽使用量而言,preconnect 比 preload 更便宜,但仍存在风险。与过多的 preload 提示一样,过多的 preconnect 提示仍会占用 TLS 证书方面的带宽。请注意,不要预先连接到过多的来源,否则可能会导致带宽争用。
总结
如果您知道自己很快会从第三方网域下载某些内容,但不知道相应资源的确切网址,那么这两个资源提示有助于提高网页速度。例如,分发 JavaScript 库、图片或字体的 CDN。请注意限制,仅对最重要的资源使用 preconnect,对其他资源使用 dns-prefetch,并始终在实际应用中衡量影响。