預加載系列一: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 Prefetch
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.chrome

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

  1. chrome 會自動把當前頁面的全部帶href的link的dns都prefetch一遍瀏覽器

  2. 須要手動添加link標籤的場景是:你預計用戶在後面的訪問中須要用到當前頁面的全部連接都不包含的域名服務器

看來,咱們原先的姿式是不對的~網絡

驗證

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

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

在chrome裏打開他,而後訪問 chrome://histograms/DNS.PrefetchQueue ,看到以下統計結果
4---.png
固然,上圖並不能說明什麼問題,只能看出:從啓動chrome到訪問剛剛這個測試頁面,一共有88次dns prefetching,其中67次直接命中耗時0ms,有4次耗時5ms。不過,若是把測試頁面改爲下面這個樣子再跑一次就有點意思了:異步

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

統計結果變成了:
20---.png

能夠看出:由於頁面裏有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的域名。事實上,咱們已經這麼作了,具體能夠看這篇文章:《預加載系列二:讓File Prefetching絲絲潤滑無痛無癢》

本文首發於個人
SegmentFault專欄:http://segmentfault.com/a/1190000004336839
我的技術博客:http://delai.me/code/file-frefetching/轉載請註明出處

相關文章
相關標籤/搜索