Resouce Hints 讓我們可以幫助瀏覽器尋找到它將要用到的資源,然後提前下載它們以期獲得更佳的效能。
對於現代化的網站,速度優化需要的不再僅僅是最小化初始下載大小和 critical rendering path ,我們還可以通過儘早地解析並預取資源來優化資源的載入。
“預取”只是在一個資源被需要之前就開始下載的行為,以期來提供快速、即時的體驗。
Dns-prefetch
Dns-prefetch 是在瀏覽器請求資源之前,開啟資源所在的每個域的 DNS 解析的過程,目的是當瀏覽器真正地請求資源時節省 DNS 解析時間。
你可以把 DNS 解析理解成瀏覽器為了將
domain/hostname
轉化成一個訪問資源所需 ip 地址的必經過程(這個過程就是把對使用者友好的 url,比如 www.medium.com/,轉成 http://80.72.139.1.0)。
通過檢查 amazon.com 站點的原始碼,你會在其主頁的頂部找到以下程式碼:
<link rel='dns-prefetch' href='//g-ecx.images-amazon.com'>
<link rel='dns-prefetch' href='//completion.amazon.com'>
複製程式碼
Amazon.com 使用 DNS-prefetch 來解析多個域名,從中獲取不同的資源,如影像、JS 和 CSS 檔案。當瀏覽器遇到這些 URLs 時,它首先檢查快取,如果沒有命中快取,則向 DNS 伺服器傳送請求來解析出域名相應的 IP 地址。這些請求在後臺處理並不會阻塞頁面的渲染。
DNS 查詢的成本是很低的——它們只通過網路傳送幾百個位元組,因此沒有太大的風險。
你可以在這個網站檢查瀏覽器是否支援 DNS-prefetch:caniuse.com/#feat=link-…
Preconnect
如果你使用的是 HTTPS,它可以完成與某個域建立連線的所有工作,包括 DNS 查詢、TCP 握手和TSL 協商。
preconnect 可以通過 提前執行這項工作來遮蔽高延遲連線 以及削減啟動請求的寶貴時間:
<link rel="preconnect" href="//example.com">
複製程式碼
你可以在這個網站檢查瀏覽器是否支援此功能:caniuse.com/#feat=link-…
Prefetch
摘自 MDN:
Link prefetching 是一種瀏覽器機制,這種機制利用瀏覽器的空閒時間來下載或者預取使用者可能在不久的將來訪問的文件。一個 web 頁面向瀏覽器提供一組 prefetching hints,然後瀏覽器載入完頁面後,開始靜默地預取指定文件並將其儲存在快取中。當使用者訪問其中一個預取文件時,可以快速地將其從瀏覽器的快取中提取出來。
因此,這意味著 prefetch 用於獲取和快取資源,這些資源將在使用者可能訪問的後續路由中使用。
prefetch 可以用於一個帶有 prefetch
和 url
屬性的 link
標籤:
<link rel="prefetch" href="//example.com/next-page.html" as="html" crossorigin="use-credentials">
<link rel="prefetch" href="/library.js" as="script">
複製程式碼
as
屬性是可選的,它用來幫助瀏覽器的 preloader 優化預取過程。
crossorigin
屬性也是可選的,它允許你為給定的資源指定跨源策略。
只有能夠被快取的元素應該使用預取功能。
你可以在這個網站檢查瀏覽器是否支援此功能:caniuse.com/#feat=link-…
Preload
preload 類似於 prefetch,區別在於 prefetch 用於發起對後續路由中將要使用的資源的請求,而 preload 則用於預取同一個頁面中將要用到的資源。
<link rel="preload" href="/library.js" as="script">
複製程式碼
prefetch 是一個可選的、低優先順序的用於獲取在後續的導航中可能用到的一個資源的 fetc;preload 是一個強制的、高優先順序的用於獲取當前導航必需資源的 fetch。
如果你使用了懶載入來加速頁面的載入,或者在 JavaScript 或 CSS 內部告訴了瀏覽器存在的資源,比如 web 字型,那麼 preload 將非常有用。
這還有一個有趣的用例,你可以對預載入的資源進行更細粒度的控制:
<script>
function preloadFinished(e) { ... }
function preloadError(e) { ... }
</script>
<!-- listen for load and error events -->
<link rel="preload" href="app.js" as="script" onload="preloadFinished()" onerror="preloadError()">
複製程式碼
你可以在這個網站檢視瀏覽器的支援情況:caniuse.com/#feat=link-…
從 Safari Technology Preview 13 版本也開始提供這個功能了:developer.apple.com/safari/tech…
Prerender
預渲染是一種告訴瀏覽器預取並執行給定資源的方法。
你可以通過插入 rel
為 prerender
的 link
元素來觸發預渲染,例如:
<link rel='prerender' href='//pagetoprerender/landing.html'>
複製程式碼
你可以將預渲染視為在新選項卡中載入頁面,只是該選項卡對使用者隱藏,直到使用者發出請求時才呈現。
由於瀏覽器會執行預渲染頁面上的所有指令碼,因此你可能會遇到一些意外的後果,比如觸發 analytics beacons,而實際上頁面並沒有被展示。你可以使用 Page Visibility API 來解決這些問題。
你應該理性地使用 prerender,因為它可能會導致頻寬和 CPU 使用的上升。你應該只在這種情況下考慮使用 prerender,那就是如果你對使用者將要使用某個資源高度自信,並且你確實提供了附加的價值。
請注意,是否啟動預渲染的決定權在於瀏覽器,它可以基於一組 預定義規則 選擇不啟動或放棄預渲染功能。
你可以在此檢視瀏覽器的支援情況:caniuse.com/#feat=link-…
Hint probability
Hint probability 是一個 link
的元素的 pr
屬性,可用於指示給定資源是否必要的概率,並且你可以將其與任何上面提到的資源提示一起使用,但是 preload 除外。
// The pr attribute expects a float value in the [0.0-1.0] range
<link rel="prefetch" href="//example.com/next-page.html" pr="0.75">
複製程式碼
這個 hint 用於幫助瀏覽器決定一個給定 hint 的執行。在裝置中資源受限的情況下,瀏覽器可以決定僅執行高可用性提示。
在執行時注入resource hints
上面提到的每個 resource hint 都可以在執行時使用 JavaScript 觸發,你只需要使用正確的屬性建立 link
元素並將其新增到頁面的 head
標籤中。
var hint =document.createElement("link")
hint.setAttribute(“rel”,”prerender”)
hint.setAttribute(“href”,”next-page.html”)
document.getElementsByTagName(“head”)[0].appendChild(hint)
複製程式碼
分析架構模式、研究使用者行為,然後迭代產品
對你的架構進行分析,找出可以從中獲取最大收益的地方:
- 每個頁面上哪個才是最重要的資源?
- 哪些操作會觸發下載其他內容?
- 哪些 assets 是在 critical rendering path 上?
研究使用者在你網站上的行為:
- 訪問次數最多的頁面是哪些?
- 使用者轉化的過程是什麼?
- 某項操作的頻次是多少?
始終使用 webpagetest 等工具在更改前後進行速度測量。
能力越大,責任越大。