fi3ework / blog

📝
861 stars 53 forks source link

[译] Prefetch & preconnect-dns 的优先级 #33

Open fi3ework opened 6 years ago

fi3ework commented 6 years ago

原文:Prefetch & preconnect-dns priority

作者: JUSTIN AVERY


如果你想要浏览器在你访问某个域名前先执行 DNS 解析,那么你使用 preconnect 和 prefetch-dns 都是可以的,这将会节省关键渲染路径的时间。本文主要分析这两者的区别,结论无法一句话概括。

概念

举个例子,当我们访问 https://responsivedesign.is/articles/prefetch-preconnect-dns-priority/ 这个页面时,最开始发生的事情是浏览器需要知道 responsivedesign.is 在哪 —— 就是我们所知道的 DNS 握手,如果你观察 网络的瀑布图, 你将会发现请求最开始的部分是水绿色的,这代表着 DNS 解析。

![]()

preconnect 和 prefetch-dns 的作用就是让 DNS 的解析尽快发生,在真正有请求发送到那个 DNS 对应的域名前就完成。这样可以在你想请求资源的时候节约时间(preconnect 比 prefetch-dns 做的多一点,不过是在 DNS 解析之后)

节约了多少时间?在上面的瀑布图示例中 DNS 解析的时间是

每个都是一百多毫秒,可是当你将他们加起来就发现有 502ms 之多,将它们从关键渲染路径的加载时间中去除掉,将获得半秒的加载提速。

dns-prefetch 和 preconnect 的区别

这两者的区别是 —— dns-prefetch 将只会做 DNS 解析,preconnect 将会做 DNS 解析,TLS 协商和 TCP 握手,这意味着要下载资源时可以额外避免两个 RTT(Rount-trip Time)。

不过当我在 Web Page Test 测试的时候似乎只避免了 DNS 解析,我无法对此做出合理的解释。可能是浏览器对 dns-prefetch 的支持要远好于 preconnect 的支持,我推测我用来测试的 Chrome 版本不完全支持,不过还是避免了 DNS 的解析。

问题 —— 顺序对优先级有影响吗?

写这篇文章的原因是当我浏览 Victoria and Albert Museum 的网站时,在检查时我发现这个网站使用如下的代码段来提前完成 DNS 的解析来节省以后的请求时间:

<link rel="dns-prefetch" href="//vanda-production-assets.s3.amazonaws.com" />

这是写在 <head> 标签中的,不过这个网站同时也使用了 <style> 标签来声明一系列的需要发送请求的背景图片,这些 background-image 声明在 dns-prefetch 标签出现,这让我不禁疑问它们谁将先被触发:

  1. 浏览器会不会在看到一个图像的 URL 后就立刻开始下载资源,因此 DNS 解析在 dns-prefetch 标签前就已经开始了。
  2. 浏览器会不会解析整个 HTML 文档后再请求资源。

测试顺序的优先级

为了测试我写了一系列的 Code Pen 来进行测试 DNS 解析在以下五种情况下会在什么时候发生,每种场景都通过 Web Page Test 来在 Chrome 和 Fast 3G 网络条件下测试,我选择这个网络条件是它们之间的差别在这种移动网络条件下会被放大(我还没用 2G 呢)。

每个 code pen 都在 head 中有一个 style 标签,设置了 background-image,它们之间的区别就是 DNS 预解析的顺序与类型不同,如下:

  1. dns-prefetch after styles
  2. dns-prefetch before styles
  3. preconnect after styles
  4. preconnect before styles
  5. No preconnect prefetch

(译者注:我不知道为啥以上链接的 code pen 中都看不到代码页面还有内容... 不过通过检查元素还是可以看到 HTML 的结构...)

没有 preconnect prefetch

没有任何 resource hint 我们可以看到一个页面通常是如何被请求的,注意 DNS 解析是关键路径的一部分:

<style>
body {background-image:url('https://s3-us-west-2.amazonaws.com/s.cdpn.io/7635/Ayers-Rock-Australia.jpg')}
</style>

Critical load path when no prefetch/preconnect of the DNS is included in the

dns-prefetch 在 styles 之后

<style>
body {background-image:url('https://s3-us-west-2.amazonaws.com/s.cdpn.io/7635/Ayers-Rock-Australia.jpg')}
</style>
<link href="https://s3-us-west-2.amazonaws.com" rel="dns-prefetch">

你可以从瀑布图中看到尽管 background-image 在 dns-prefetch 所在的 link 标签之前声明,DNS 解析还是在整个 HTML 文档解析完毕后立即开始,并且和其他页面一开始请求的资源的 DNS 解析并行执行,比如说来自 //cdnjs.cloudflare.comnormalise.css

Critical load path when preconnect is included in the after the