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

原文:Prefetch & preconnect-dns priority

作者: JUSTIN AVERY

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

概念

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

《[译] Prefetch & preconnect-dns 的优先级》

《[译] Prefetch & preconnect-dns 的优先级》

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

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

  • 150 ms —//cdnjs.cloudflare.com
  • 185 ms —//production-assets.codepen.io
  • 167 ms — //s3-us-west-2.amazonaws.com

每个都是一百多毫秒,可是当你将他们加起来就发现有 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>

《[译] Prefetch & preconnect-dns 的优先级》

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

《[译] Prefetch & preconnect-dns 的优先级》

Critical load path when preconnect is included in the after the <style> tag

dns-prefetch 在 styles 之前

如你所想,如果我们想让握手发生在它想发生的时候,在图像之前或者之后声明 DNS 预解析都是一样的。

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

《[译] Prefetch & preconnect-dns 的优先级》

Critical load path when dns-prefetch is included in the before the <style> tag

preconnect 在 styles 之后

这个测试中,我想看下 preconnect 将三个 RTT 都提前执行了能比 dns-prefetch 多节约多少时间,不幸的是根本没有区别,我需要以后再看下。

<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="preconnect" crossorigin>

《[译] Prefetch & preconnect-dns 的优先级》

Critical load path when dns-prefetch is included in the after the <style> tag

preconnect 在 styles 之前

这个测试的结果也是 DNS 的预解析立刻发生,可是同样没有看到 TCP 和 TLS 的握手..

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

《[译] Prefetch & preconnect-dns 的优先级》

Critical load path when preconnect is included in the before the <style> tag

结论

如上你可以看到,无论你将 link 标签在 head 中如何防止,只要它存在它就会完成 DNS 的预解析因此节省你浏览网页的时间。

值得为你的网站中的外部的域名都添加上预解析,尤其是图片的 CDN,字体库(比如 Google Fonts)或者外部的你可能使用的 JS 文件。

译者注

译者在今天(2018 年 7 月 26 日),对 preconnect before styles 进行了测试,用的是 Chrome Canary + 3G,如下图,可以看到 TCP 和 TLS 都紧跟着 DNS 解析发生了,期待 preconnect 被更多浏览器支持!

测试结果:Web Page Performance Test fors.codepen.io/justincavery/debug/jBVdxE

《[译] Prefetch & preconnect-dns 的优先级》

译者再注

其实这篇文章主要就说了两个点:

  1. preconnect 比 dns-prefetch 多了 TCP 和 TLS 的预解析。
  2. DOM tree 的构建要等到整个 HTML 文档下载完后才能构建完,DOM tree 上节点信息的读取要等到 DOM tree 构建完毕。
    原文作者:小蜜蜂
    原文地址: https://juejin.im/entry/5b5c047b6fb9a04fc937577f
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞