當(dāng)提到前端性能優(yōu)化時(shí)缀拭,我們首先會(huì)聯(lián)想到文件的合并织阳、壓縮眶蕉,文件緩存和開啟服務(wù)器端的 gzip 壓縮等,這使得頁面加載更快唧躲,用戶可以盡快使用我們的 Web 應(yīng)用來達(dá)到他們的目標(biāo)造挽。
資源預(yù)加載是另一個(gè)性能優(yōu)化技術(shù),我們可以使用該技術(shù)來預(yù)先告知瀏覽器某些資源可能在將來會(huì)被使用到弄痹。
引用 Patrick Hamann 的解釋:
預(yù)加載是瀏覽器對將來可能被使用資源的一種暗示饭入,一些資源可以在當(dāng)前頁面使用到,一些可能在將來的某些頁面中被使用肛真。作為開發(fā)人員谐丢,我們比瀏覽器更加了解我們的應(yīng)用,所以我們可以對我們的核心資源使用該技術(shù)蚓让。
這種做法曾經(jīng)被稱為 prebrowsing乾忱,但這并不是一項(xiàng)單一的技術(shù),可以細(xì)分為幾個(gè)不同的技術(shù):DNS-prefetch历极、subresource 和標(biāo)準(zhǔn)的 prefetch窄瘟、preconnect、prerender趟卸。
DNS 預(yù)解析 DNS-Prefetch
通過 DNS 預(yù)解析來告訴瀏覽器未來我們可能從某個(gè)特定的 URL 獲取資源蹄葱,當(dāng)瀏覽器真正使用到該域中的某個(gè)資源時(shí)就可以盡快地完成 DNS 解析。例如锄列,我們將來可能從 example.com 獲取圖片或音頻資源新蟆,那么可以在文檔頂部的 標(biāo)簽中加入以下內(nèi)容:
<link rel="dns-prefetch" >
1
<link rel="dns-prefetch" >
當(dāng)我們從該 URL 請求一個(gè)資源時(shí),就不再需要等待 DNS 的解析過程右蕊。該技術(shù)對使用第三方資源特別有用琼稻。
在 Harry Roberts 的文章中提到:
通過簡單的一行代碼就可以告知那些兼容的瀏覽器進(jìn)行 DNS 預(yù)解析,這意味著當(dāng)瀏覽器真正請求該域中的某個(gè)資源時(shí)饶囚,DNS 的解析就已經(jīng)完成了帕翻。
這似乎是一個(gè)非常微小的性能優(yōu)化,顯得也并非那么重要萝风,但事實(shí)并非如此 – Chrome 一直都做了類似的優(yōu)化嘀掸。當(dāng)在瀏覽器的地址欄中輸入 URL 的一小段時(shí),Chrome 就自動(dòng)完成了 DNS 預(yù)解析(甚至頁面預(yù)渲染)规惰,從而為每個(gè)請求節(jié)省了至關(guān)重要的時(shí)間睬塌。
預(yù)連接 Preconnect
與 DNS 預(yù)解析類似,preconnect 不僅完成 DNS 預(yù)解析,同時(shí)還將進(jìn)行 TCP 握手和建立傳輸層協(xié)議揩晴⊙悖可以這樣使用:
<link rel="preconnect" >
1
<link rel="preconnect" >
在 Ilya Grigorik 的文章中有更詳細(xì)的介紹:
現(xiàn)代瀏覽器都試著預(yù)測網(wǎng)站將來需要哪些連接,然后預(yù)先建立 socket 連接硫兰,從而消除昂貴的 DNS 查找诅愚、TCP 握手和 TLS 往返開銷。然而劫映,瀏覽器還不夠聰明违孝,并不能準(zhǔn)確預(yù)測每個(gè)網(wǎng)站的所有預(yù)鏈接目標(biāo)。好在泳赋,在 Firefox 39 和 Chrome 46 中我們可以使用 preconnect 告訴瀏覽器我們需要進(jìn)行哪些預(yù)連接雌桑。
預(yù)獲取 Prefetching
如果我們確定某個(gè)資源將來一定會(huì)被使用到,我們可以讓瀏覽器預(yù)先請求該資源并放入瀏覽器緩存中祖今。例如筹燕,一個(gè)圖片和腳本或任何可以被瀏覽器緩存的資源:
<link rel="prefetch" href="image.png">
1
<link rel="prefetch" href="image.png">
與 DNS 預(yù)解析不同,預(yù)獲取真正請求并下載了資源衅鹿,并儲(chǔ)存在緩存中撒踪。但預(yù)獲取還依賴于一些條件,某些預(yù)獲取可能會(huì)被瀏覽器忽略大渤,例如從一個(gè)非常緩慢的網(wǎng)絡(luò)中獲取一個(gè)龐大的字體文件制妄。并且,F(xiàn)irefox 只會(huì)在瀏覽器閑置時(shí)進(jìn)行資源預(yù)獲取泵三。
在 Bram Stein 的帖子中說到耕捞,這對 webfonts 性能提升非常明顯。目前烫幕,字體文件必須等到 DOM 和 CSS 構(gòu)建完成之后才開始下載俺抽,使用預(yù)獲取就可以輕松繞過該瓶頸。
注意:要測試資源的預(yù)獲取有點(diǎn)困難较曼,但在 Chrome 和 Firefox 的網(wǎng)絡(luò)面板中都有資源預(yù)獲取的記錄磷斧。還需要記住,預(yù)獲取的資源沒有同源策略的限制捷犹。
Subresources
這是另一個(gè)預(yù)獲取方式弛饭,這種方式指定的預(yù)獲取資源具有最高的優(yōu)先級(jí),在所有 prefetch 項(xiàng)之前進(jìn)行:
<link rel="subresource" href="styles.css">
1
<link rel="subresource" href="styles.css">
根據(jù) Chrome 文檔:
rel=prefetch 為將來的頁面提供了一種低優(yōu)先級(jí)的資源預(yù)加載方式萍歉,而 rel=subresource 為當(dāng)前頁面提供了一種高優(yōu)先級(jí)的資源預(yù)加載侣颂。
所以,如果資源是當(dāng)前頁面必須的枪孩,或者資源需要盡快可用憔晒,那么最好使用 subresource 而不是 prefetch藻肄。
預(yù)渲染 Prerender
這是一個(gè)核武器,因?yàn)?prerender 可以預(yù)先加載文檔的所有資源:
<link rel="prerender" >
1
<link rel="prerender" >
Steve Souders 在他的一篇文章中寫到:
這類似于在一個(gè)隱藏的 tab 頁中打開了某個(gè)鏈接 – 將下載所有資源拒担、創(chuàng)建 DOM 結(jié)構(gòu)嘹屯、完成頁面布局、應(yīng)用 CSS 樣式和執(zhí)行 JavaScript 腳本等澎蛛。當(dāng)用戶真正訪問該鏈接時(shí)抚垄,隱藏的頁面就切換為可見蜕窿,使頁面看起來就是瞬間加載完成一樣谋逻。Google 搜索在其即時(shí)搜索頁面中已經(jīng)應(yīng)用該技術(shù)多年了,微軟也宣稱將在 IE11 中支持該特性桐经。
需要注意的是不要濫用該特性毁兆,當(dāng)你知道用戶一定會(huì)點(diǎn)擊某個(gè)鏈接時(shí)才可以進(jìn)行預(yù)渲染,否則瀏覽器將無條件地下載所有預(yù)渲染需要的資源阴挣。
更多相關(guān)討論:
所有預(yù)加載技術(shù)都存在一個(gè)潛在的風(fēng)險(xiǎn):對資源預(yù)測錯(cuò)誤气堕,而預(yù)加載的開銷(搶占 CPU 資源,消耗電池畔咧,浪費(fèi)帶寬等)是高昂的茎芭,所以必須謹(jǐn)慎行事。雖然很難確定用戶下一步將訪問哪些資源誓沸,但高可信的場景確實(shí)存在:
如果用戶完成一個(gè)帶有明顯結(jié)果的搜索梅桩,那么結(jié)果頁面很可能會(huì)被加載
如果用戶進(jìn)入到登陸頁面,那么登陸成功的頁面很可能會(huì)被加載
如果用戶閱讀一個(gè)多頁的文章或訪問一個(gè)分頁的結(jié)果集拜隧,那么下一頁很可能會(huì)被加載
最后宿百,使用 Page Visibility API 可以防止頁面真正可見前被執(zhí)行。
Preload
preload 是一個(gè)新規(guī)范洪添,與 prefetch 不同(可能被忽略)的是垦页,瀏覽器一定會(huì)預(yù)加載該資源:
<link rel="preload" href="image.png">
1
<link rel="preload" href="image.png">
雖然該規(guī)范還沒有被所有瀏覽器兼容,但其背后的思想還是非常有意思的干奢。
總結(jié)
預(yù)測用戶下一步將訪問哪些資源是困難的痊焊,需要進(jìn)行大量的測試,但是這帶來的性能提升是明顯的忿峻。如果我們愿意嘗試這些預(yù)獲取技術(shù)宋光,一定會(huì)顯著提升用戶的體驗(yàn)。
zhjm 發(fā)布于 2016-08-12 11:53:43 瀏覽:1138 類型:原創(chuàng) - 隨筆 分類:性能優(yōu)化 - html優(yōu)化 二維碼: 作者原創(chuàng) 版權(quán)保護(hù)