DNS Prefetching - 預先做DNS解析,幫助網頁載入速度更快
前陣子看見Addy Osmani大大在Facebook上發表了一張圖片(原文)。
在研究淘寶SEO策略時有略略看到頁面上出現這樣的設定,但對於網站效能提升這一塊比較陌生的我,並沒有做太多的研究(只知道是做什麼用的),剛好藉這次機會來看看相關資料並做整理。
什麼是DNS Prefetching?
預先做DNS解析(domain name resolution),將人類可理解的domain name,轉為IP address。瀏覽器載入頁面和資源時需做DNS解析,但若等到瀏覽該頁或要下載資源時才做DNS解析就太遲了(使用者需要等待一段時間),因此可預先執行。(關於DNS Lookup流程可參考 DNS 名稱解析程序。)
預先做DNS解析的好處是使用者瀏覽之後的頁面時,可減少DNS Lookup的時間,感覺速度變快了。
如何使用DNS Prefetching?
在HTML的 <head>
加入 <link rel="dns-prefetch" href="https://my-site.com">
。
使用這個指令後,頁面上 <a>
的連結也都會開啟DNS Prefetching。
附註,DNS Prefetching在https下是無法使用的。若要在https下開啟DNS Prefetching,必須在 <head>
加上 <meta http-equiv="x-dns-prefetch-control" content="on">
才能啟動DNS Prefetching。但只能啟動連結,而無法啟動手動設定的資源。
順道一提,<link rel="dns-prefetch" href="//host_name_to_prefetch.com">
和 <link rel="dns-prefetch" href="http://host_name_to_prefetch.com">
意義是相同的,「//」表示網址起始是一個host name。
使用DNS Prefetching的時機
-
該頁面有許多靜態資源但放在各個不同的domain底下,例如圖檔、CSS檔案、JS檔案等:例如,在這個頁面或這個網站將圖片放在
http://a.img.com.tw
和http://b.img.com.tw
這些domain底下。我希望瀏覽該頁面時能先對這兩個domain name做DNS Prefetching,於是可在<head>
加上<link rel="dns-prefetch" href="http://a.img.com.tw"> <link rel="dns-prefetch" href="http://b.img.com.tw">
-
該頁會轉跳到不同domain下的頁面,因此可在指令先指定對轉跳的domain做DNS Prefetching
適合的對象
- 電商網站的商品頁大量載入不同domain下的商品圖,例如:淘寶
- 手機網頁,需要提高頁面載入完成的速度
成效評估
測試範例
拿我們家露天拍賣的測試機商品頁來看看...
尚未做DNS Prefetch之前
做了DNS Prefetch之後
我加了這幾條指令到 <head>
裡面...
<link rel="dns-prefetch" href="http://a.rimg.com.tw">
<link rel="dns-prefetch" href="http://b.rimg.com.tw">
<link rel="dns-prefetch" href="http://c.rimg.com.tw">
<link rel="dns-prefetch" href="http://d.rimg.com.tw">
<link rel="dns-prefetch" href="http://e.rimg.com.tw">
多7次DNS Prefetch,其中不需做DNS Prefetch的有7次,完全命中。由於在上一頁的時候保留了DNS Lookup的紀錄,因此省了7次的DNS Lookup。
拿淘寶的商品頁來看看
多9次DNS Prefetch,其中不需做DNS Prefetch的有4次,大約減少了一半。
附註:可以用來觀察結果的指令
chrome://histograms/DNS.PrefetchQueue
about:histograms/DNS (可看更詳細的資料)
about:dns (可看更詳細的資料)
使用DNS Prefetching的好處?
花小量的傳輸(不到100 bytes),卻平均可節省200ms。
(有興趣的話可參考DNS Prefetching - The Chromium Projects)
對SEO來說,網站速度也是Ranking Factor之一,提高下載速度就可提高排名。
減少DNS Lookup 次數的相關議題
假設在頁面上有許多資源,例如:圖片、CSS檔案、JS檔案,這些都放在同一個domain name底下,這時瀏覽器針對每個domain只會開一個連線。也就是說,假設有10個檔案放在同一個domain之下,每個檔案需要100ms才能下載完,那個預計載完資源需要 10*100=1000ms
。但若我們將這10個檔案分別放在2個不同的domain下,就可以開兩條連線檔案同時下載,那麼只要花 5*100=500ms
即可,減少了一半的時間。但也不是說domain愈多愈好,因為DNS Lookup需要時間,因此建議維持2~4個不同的domain name即可。
瀏覽器比較:Chrome、Firefox、IE
Chrome
- Chrome會記住最近使用的10個domain,並且在開啟瀏覽器時自動解析,因此在開啟這些常用頁面的時候,並不會有DNS Lookup的延遲狀況,大約節省了200ms或更多。打開你的Chrome,使用指令
chrome://dns
來看看。 - 本機作業系統對DNS的快取是有限的,大約只能暫存50~200個domain name。一旦超過了這個限制,便會移除過去使用過的domain name來存放新的domain name。而選取移除的domain name只靠瀏覽的時間決定,可能會造成經常使用的domain name查詢結果被移除,被迫常常對這個domain name進行查詢。Chrome嘗試修正這樣的機制,所以會猜測哪些domain name是使用者近期可能會用到的,然後標記為常用,使其能保存久一點。
(有興趣的話可參考可參考 DNS Prefetching - The Chromium Projects)。
而Chrome類似其他瀏覽器的其他設定都已忽略,似乎不希望使用者更改預設值。因此直接清除。
- chrome打開:
chrome://net-internals/#dns
- 點擊按鈕「clean host cache」
Firefox
network.dns.disablePrefetch
:若設定為true,則會關閉瀏覽器DNS Prefethcing的功能。network.dns.disablePrefetchFromHTTPS
:若設定為false,則會開啟使用HTTPs的網站的DNS Prefethcing功能。在HTTPs的網站下,DNS Prefethcing功能預設是關閉的,必須經此手動開啟。network.dnsCacheExpiration
:預設DNS暫存1分鐘network.dnsCacheEntries
:預設DNS暫存20個network.http.keep-alive.timeout
:TCP/IP連線idle一段時間後才會被釋放掉,預設是5分鐘。好處是避免重覆DNS Lookup太快發生。
IE
DnsCacheTimeout
:預設DNS暫存30分鐘。KeepAliveTimeout
:TCP/IP連線idle一段時間後才會被釋放掉,預設是1分鐘。好處是避免重覆DNS Lookup太快發生。ServerInfoTimeout
:就算沒有KeepAliveTimeout
,假設我們查到了IP位置,並在使用一段時間內都沒有發生錯誤,那麼這段間內都不會對此domain name做DNS Lookup。預設是2分鐘。
References
- Controlling DNS prefetching
- DNS Prefetching for Firefox (blog post)
- Google Chrome handles DNS prefetching control
- 预加载-有赞-DNS
- DNS Prefetching的两三事
- DNS Prefetching - The Chromium Projects
- PageSpeed: Parallelize downloads across hostnames
- 完整主機名稱: Fully Qualified Domain Name (FQDN)、19.1.2 DNS 的主機名稱對應 IP 的查詢流程
- Firefox prefetching: what you need to know
- HTTP協議頭部與Keep-Alive模式詳解
由於部落格搬家了,因此在新落格也放了一份,未來若有增刪會在這裡更新-DNS Prefetching - 預先做 DNS 解析,幫助網頁載入速度更快。
留言