預加載系列一:DNS Prefetching 的正確使用姿式

發現

不少人都知道現代瀏覽器都支持 DNS 的預解析,學名:DNS Prefetching。用法也很簡單,就是在html代碼里加入這樣的 link 標籤css

<link rel="dns-prefetch" href="//delai.me">複製代碼

咱們以前的用法是在 Head 爲2個 靜態資源服務器的域名 和 日誌圖片的域名 建了3條 dns-prefetch link。html

<link rel="dns-prefetch" href="//tj.koudaitong.com/" />  
<link rel="dns-prefetch" href="//imgqn.koudaitong.com/" />  
<link rel="dns-prefetch" href="//kdt-static.qiniudn.com/" />複製代碼

我最近給移動web 關鍵靜態資源作 File Prefetching,順手看了下Chromium 和 Firefox 關於 DNS Prefetching 的官方文檔看到這麼一句:web

Manual Prefetchchrome

Chromium uses the "href" attribute of hyperlinks to find host names to prefetch. However, some of those hyperlinks may be redirects, for example if the site is trying to count how many times the link is clicked. In those situations, the "true" targeted domain is not necessarily discernible by examining the content of a web page, and so Chromium not able to prefetch the final targeted domain.瀏覽器

上面這段文字包含兩個信息:bash

  • chrome 會自動把當前頁面的全部帶href的link的dns都prefetch一遍
  • 須要手動添加link標籤的場景是:你預計用戶在後面的訪問中須要用到當前頁面的全部連接都不包含的域名

驗證

我寫了一個測試頁面,代碼是這樣的:服務器

<html>  
<head></head>  
<body>  
    <a href="http://a.youzan.com">a.youzan.com</a>
    <a href="http://b.youzan.com">b.youzan.com</a>
    <a href="http://c.youzan.com">c.youzan.com</a>
    <a href="http://d.youzan.com">d.youzan.com</a>
</body>  
</html>複製代碼

在 Chrome 裏打開他,而後訪問 chrome://histograms/DNS.PrefetchQueue ,看到以下統計結果網絡

chrome-prefetch
chrome-prefetch

<html>  
<head></head>  
<body>  
    <a href="http://a.youzan.com">a.youzan.com</a>
    <a href="http://b.youzan.com">b.youzan.com</a>
    <a href="http://c.youzan.com">c.youzan.com</a>
    <a href="http://d.youzan.com">d.youzan.com</a>
    <a href="http://a1.youzan.com">a1.youzan.com</a>
    <a href="http://b1.youzan.com">b1.youzan.com</a>
    <a href="http://c1.youzan.com">c1.youzan.com</a>
    <a href="http://d1.youzan.com">d1.youzan.com</a>
    <a href="http://a2.youzan.com">a2.youzan.com</a>
    <a href="http://b2.youzan.com">b2.youzan.com</a>
    <a href="http://c2.youzan.com">c2.youzan.com</a>
    <a href="http://d2.youzan.com">d2.youzan.com</a>
    <a href="http://a3.youzan.com">a3.youzan.com</a>
    <a href="http://b3.youzan.com">b3.youzan.com</a>
    <a href="http://c3.youzan.com">c3.youzan.com</a>
    <a href="http://d3.youzan.com">d3.youzan.com</a>
    <a href="http://a4.youzan.com">a4.youzan.com</a>
    <a href="http://b4.youzan.com">b4.youzan.com</a>
    <a href="http://c4.youzan.com">c4.youzan.com</a>
    <a href="http://d4.youzan.com">d4.youzan.com</a>
</body>  
</html>複製代碼

統計結果變成了:dom

dns-prefetch-2
dns-prefetch-2

能夠看出:由於頁面裏有20個a標籤帶href屬性,chrome作了20次dns prefetching,其中耗時爲0的次數比以前加了4,那是由於頭4個域名在上一次跑測試頁面的時候已經被prefetch過了本地已經有記錄,直接命中。其他的16個dns prefetching 耗時基本上離散分佈不甚相同。異步

結論

實際狀況如文檔所說,個人理解也是對,咱們以前的使用姿式有點問題。

正確的使用姿式

1.對靜態資源域名作手動dns prefetching。
2.對js裏會發起的跳轉、請求作手動dns prefetching。
3.不用對超連接作手動dns prefetching,由於chrome會自動作dns prefetching。
4.對重定向跳轉的新域名作手動dns prefetching,好比:頁面上有個A域名的連接,但訪問A會重定向到B域名的連接,這麼在當前頁對B域名作手動dns prefetching是有意義的。

其餘

1.假設頁面Head裏面有個css連接, 在當前頁的Head里加上對應的手動dns prefetching的link標籤,實際上並無好處。

2.廣泛來講合理的dns prefetching能對頁面性能帶來50ms ~ 300ms的提高,有人作了這方面的統計。

3.如 Chromium 的官方文檔所說,dns prefetching的網絡消耗是極低極低的:

Each request typically involves sending a single UDP packet that is under 100 bytes out, and getting back a response that is around 100 bytes. This minimal impact on network usage is compensated by a significant improvement in user experience.

4.如chromium的官方文檔所說,chrome使用8個線程專門作dns prefetching 並且chrome自己不作dns記錄的cache,是直接從操做系統讀dns —— 也就是說,直接修改系統的dns記錄或者host是能夠直接影響chrome的。

5.手動dns prefetching的代碼實際上仍是會增長html的代碼量的,特別是域名多的狀況下。
因此,最優的方案應該是:經過js初始化一個iframe異步加載一個頁面,而這個頁面裏包含本站全部的須要手動dns prefetching的域名。事實上,咱們已經這麼多了,稍後會再發一篇博文詳細介紹。

本文首發於有贊技術博客:tech.youzan.com/dns-prefetc…

相關文章
相關標籤/搜索