Web 性能优化之 dns-prefetch 和 preconnect

dns-prefetch

当我们打开一个网页后,这个网页后续可能还会使用到其他域的资源,如果我们能提前对该域进行 DNS 解析的话,那是必会减少后续的请求延迟。dns-prefetch 尝试在请求资源之前解析域名。这可能是后面要加载的文件,也可能是用户尝试打开的链接目标。

为什么要使用 dns-prefetch?

当浏览器从(第三方)服务器请求资源时,必须先将该 跨源 域名解析为 IP 地址,然后浏览器才能发出请求,此过程称为 DNS 解析。对于打开了与许多第三方的连接的网站,DNS 解析可能会给请求增加明显的延迟,此延迟可能会大大降低加载性能。特别是如果该域的信息不在浏览器或系统的 DNS 缓存中,或者如果 DNS 服务器响应慢的情况下。

dns-prefetch 可帮助开发人员掩盖 DNS 解析延迟。HTML <link> 元素通过设置 rel 属性值为 dns-prefetch 提供此功能。然后在 href 属性中指明要跨源的域名:

语法

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

最佳实践

首先dns-prefetch 仅对跨源域上的 DNS 查找有效,因此请避免使用它来指向你的站点或域。这是因为,到浏览器看到提示时,你的站点背后的 IP 已经被解析了。

其次,还可以通过使用 HTTP Link 字段将 dns-prefetch(以及其他资源提示)指定为 HTTP 标头(响应头)之一:

Link: <https://fonts.googleapis.com/>; rel=dns-prefetch

再其次,考虑将 dns-prefetchpreconnect 提示配对。dns-prefetch 只执行 DNS 查询,而 preconnect 则是建立与服务器的连接。这个过程包括 DNS 解析,以及建立 TCP 连接,如果是 HTTPS 网站,就进一步执行 TLS 握手。将这两者结合起来,可以进一步减少跨源请求的感知延迟。你可以像这样安全地将它们结合起来使用:

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

组合使用这两者 preconnectdns-prefetch,是因为并非所有浏览器都已经实现了 preconnect,不支持 preconnect 的浏览器仍然可以通过回退到 dns-prefetch 来获得更多好处。由于这是 HTML 特性,因此容错性很强。如果浏览器也不支持 dns-prefetch 提示(或任何其他资源提示),则网站不会中断,只是不会获得它提供的好处。

注意事项

如果页面需要建立与许多第三方域的连接,则将它们预先连接会适得其反。preconnect 提示最好仅用于最关键的连接。对于其他的连接,只需使用 <link rel="dns-prefetch"> 即可节省第一步——DNS 查询——的时间。

preconnect

在速度较慢的网络中建立连接往往需要很长时间,尤其是在安全连接方面。

preconnect 它允许开发者告诉浏览器提前建立到特定域的连接,包括 DNS 解析,TCP 握手,以及可选的 TLS 协商。这样做的好处在于,当用户真正需要从这些域名加载资源时(例如,CSS、JavaScript 文件或者图片),浏览器已经完成了准备工作,可以直接开始资源的传输。这减少了延迟,提高了页面的加载速度。

预连接过程涵盖了多个阶层的网络成本:

  1. DNS 查找:将域名转换成 IP 地址。
  2. TCP 握手:建立一条到服务器的确认连接的过程。
  3. TLS 协商:如果资源通过 HTTPS 加载,还需要进行 TLS 握手以确保通信的安全性。

语法

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

注意事项

虽然 <link rel="preconnect"> 消耗的成本不高,但它仍然会占用宝贵的 CPU 时间,尤其是在安全连接上。如果没有在 10 秒内使用连接,此问题尤其糟糕,因为浏览器会关闭连接,浪费所有早期连接工作。

参考

MDN - 使用 dns-prefetch
Google Developers - 预先连接到必需的源

> cd ..