使用资源提示协助浏览器

在上一个关于优化资源加载的模块中,您学习了 CSS 和 JavaScript 等各种页面资源如何影响页面加载速度,以及如何优化它们及其交付以加快页面渲染速度。现在是深入了解资源加载更高级方面的好时机,这涉及到通过使用资源提示来帮助浏览器更快地加载它们。

资源提示可以通过告知浏览器如何加载和确定资源优先级,帮助开发者进一步优化页面加载时间。最初引入了一组资源提示,例如 preconnectdns-prefetch。但随着时间的推移,preload 和 Fetch Priority API 也相继推出,以提供其他功能。

资源提示指示浏览器提前执行某些操作,这些操作可以提高加载性能。资源提示可以执行诸如提前执行 DNS 查找、提前连接到服务器,甚至在浏览器通常发现资源之前就提取资源等操作。

资源提示可以在 HTML 中指定(最常见的是在 <head> 元素中尽早指定),也可以设置为 HTTP 标头。在本模块的范围内,将介绍 preconnectdns-prefetchpreload,以及 prefetch 提供的推测性提取行为。

preconnect

preconnect 提示用于建立与您从中提取关键资源的其他来源的连接。例如,您可能将图片或素材托管在 CDN 或其他跨域来源上

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

通过使用 preconnect,您可以预见到浏览器计划在不久的将来连接到特定的跨域服务器,并且浏览器应尽快打开该连接,最好是在等待 HTML 解析器或预加载扫描器执行此操作之前。

如果页面上有大量跨域资源,请对当前页面最关键的资源使用 preconnect

A screenshot of connection timings for a resource in the network panel of Chrome DevTools. The connection setup includes stall time, proxy negotiation, DNS lookup, connection setup, and TLS negotiation.
Chrome DevTools 网络面板中看到的连接计时可视化图。preconnect 可以通过更早地建立连接而不是在发现跨域资源时建立连接来缓解红色框内的计时,这些计时与设置与跨域服务器的连接有关。

preconnect 的常见用例是 Google 字体。Google 字体建议您 preconnect 到提供 @font-face 声明的 https://fonts.googleapis.com 域,以及提供字体文件的 https://fonts.gstatic.com 域。

<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>

crossorigin 属性用于指示是否必须使用跨域资源共享 (CORS)来提取资源。当使用 preconnect 提示时,如果从来源下载的资源使用 CORS(例如字体文件),则需要将 crossorigin 属性添加到 preconnect 提示。

dns-prefetch

虽然尽早打开与跨域服务器的连接可以显着缩短初始页面加载时间,但一次建立与许多跨域服务器的连接可能既不合理也不可行。如果您担心过度使用 preconnect,那么成本低得多的资源提示是 dns-prefetch 提示。

顾名思义,dns-prefetch 不会建立与跨域服务器的连接,而只是提前为其执行 DNS 查找DNS 查找发生在域名解析为其底层 IP 地址时。虽然设备和网络级别的 DNS 缓存层有助于使此过程通常很快,但它仍然需要一些时间。

<link rel="dns-prefetch" href="https://fonts.googleapis.com">
<link rel="dns-prefetch" href="https://fonts.gstatic.com">

DNS 查找相当廉价,并且由于其成本相对较低,因此在某些情况下,它们可能是比 preconnect 更合适的工具。特别是,在链接导航到您认为用户很可能关注的其他网站的情况下,它可能是理想的资源提示。dnstradamus 就是这样一种工具,它使用 JavaScript 自动执行此操作,并使用 Intersection Observer API 在链接到其他网站的链接滚动到用户的视口中时,将 dns-prefetch 提示注入到当前页面的 HTML 中。

preload

preload 指令用于为呈现页面所需的资源启动早期请求

<link rel="preload" href="/lcp-image.jpg" as="image">

preload 指令应仅限于后期发现的关键资源。最常见的用例是字体文件、通过 @import 声明提取的 CSS 文件,或 CSS background-image 资源,这些资源很可能是最大内容绘制 (LCP) 候选对象。在这种情况下,这些文件不会被预加载扫描器发现,因为该资源是在外部资源中引用的。

preconnect 类似,如果您预加载 CORS 资源(例如字体),则 preload 指令需要 crossorigin 属性。如果您未添加 crossorigin 属性(或为非 CORS 请求添加它),则浏览器会两次下载资源,从而浪费本可以更好地用于其他资源的带宽。

<link rel="preload" href="/font.woff2" as="font" crossorigin>

在前面的 HTML 代码段中,浏览器被指示使用 CORS 请求预加载 /font.woff2,即使 /font.woff2 与域位于同一域上也是如此。

prefetch

prefetch 指令用于为可能用于未来导航的资源启动低优先级请求

<link rel="prefetch" href="/next-page.css" as="style">

此指令在很大程度上遵循与 preload 指令相同的格式,只是 <link> 元素的 rel 属性使用值 "prefetch" 而已。但是,与 preload 指令不同,prefetch 在很大程度上是推测性的,因为您正在为未来导航启动资源提取,而未来导航可能会也可能不会发生。

在某些情况下,prefetch 可能是有益的,例如,如果您在网站上识别出大多数用户都会完整遵循的用户流程,那么对这些未来页面的渲染关键资源进行 prefetch 可以帮助缩短它们的加载时间。

Fetch Priority API

您可以通过 Fetch Priority API 及其 fetchpriority 属性来提高资源的优先级。您可以将该属性与 <link><img><script> 元素一起使用。

<div class="gallery">
  <div class="poster">
    <img src="img/poster-1.jpg" fetchpriority="high">
  </div>
  <div class="thumbnails">
    <img src="img/thumbnail-2.jpg" fetchpriority="low">
    <img src="img/thumbnail-3.jpg" fetchpriority="low">
    <img src="img/thumbnail-4.jpg" fetchpriority="low">
  </div>
</div>

默认情况下,图像以较低的优先级提取。在布局之后,如果发现图像位于初始视口内,则优先级将提高到优先级。在前面的 HTML 代码段中,fetchpriority 立即告诉浏览器以优先级下载较大的 LCP 图像,而不太重要的缩略图图像则以较低的优先级下载。

现代浏览器分两个阶段加载资源。第一阶段保留给关键资源,并在所有阻止脚本下载并执行完毕后结束。在此阶段,优先级资源可能会延迟下载。通过使用 fetchpriority="high",您可以提高资源的优先级,使浏览器能够在第一阶段下载它。

资源提示演示

测验一下您的知识

preconnect 资源提示有什么作用?

打开与跨域服务器的连接,包括 DNS 查找,以及在浏览器原本会发现它之前进行的连接和 TLS 协商。
正确!
仅对跨域服务器执行 DNS 查找。
再试一次。

Fetch Priority API 让您能够做什么?

指定下载当前页面的 HTML 的优先级。
再试一次。
指定 <link><img><script> 元素的相对优先级。
正确!

何时应使用 prefetch 提示?

对于用户可能需要的任何和所有资源或页面,无论他们将来是否实际需要它们。
再试一次。
当您高度确信用户需要您打算预提取的资源或页面时。
正确!
如果用户没有明确表示偏好减少数据使用量。
正确!

下一步:图片性能

到现在为止,您可能已经开始对您在页面 HTML、<head> 元素和资源提示方面的通用性能注意事项的知识感到相当自信了。但是,还有一些额外的优化是特定于页面通常加载的不同资源类型的。接下来,下一个模块将介绍图片性能,它可以帮助您使您网站的图片尽可能快地加载,而无论用户使用何种设备。