摘要:例如,將獲得最高優先級,而將獲得低優先級或中優先級。不帶屬性的的優先級將會等同于異步請求。對使用屬性,不然將不會從中獲益。因此,在標記中聲明以被掃描器掃描。
這是 Web 性能優化的第 6 篇,上一篇在下面看點擊查看:
Web 性能優化:使用 Webpack 分離數據的正確方法
Web 性能優化:圖片優化讓網站大小減少 62%
Web 性能優化:緩存 React 事件來提高性能
Web 性能優化:21種優化CSS和加快網站速度的方法
Web 性能優化:理解及使用 JavaScript 緩存
今天,我們將深入研究Chrome 的網絡棧,以明確 web 加載原語(如<link rel= preload > & ) 背后的工作原理,以便你能夠更有效地使用它們。
想閱讀更多優質文章請猛戳GitHub博客,一年百來篇優質文章等著你!
如其他文章所述,preload 是一個聲明式 fetch,可以強制瀏覽器在不阻塞 document 的 onload 事件的情況下請求資源。
Prefetch 告訴瀏覽器這個資源將來可能需要,但是什么時間加載這個資源是由瀏覽器來決定的。
在預加載(perload)之前,網絡請求從這里開始,預加載之后,它在解析時從左向右移動
使用預加載(perload)的一些案例在詳細介紹 預加載(perload) 之前,先來看看一些使用 預加載(perload) 的案例。
Housing.com 在對他們的漸進式 Web 應用程序的腳本轉用 proload 看到大約縮短了10%的可交互時間。
Shopify 使用 preload 加載 Web字體后,Chrome 桌面版)的文本繪制時間(1.2秒)提高了50%,這完全解決了他們的文字閃動問題。
左邊:使用 preload,右邊:不使用 preload
使用 加載字體
Treebo,印度最大的旅館網站之一,在 3G 網絡下對其桌面版試驗,在對其頂部圖片和主要的 Webpack 打包文件使用 preload 之后,在首屏繪制和可交互延遲分別減少了 1s。
同樣的,在對自己的漸進式 Web 應用程序主要打包文件使用 preload 之后,Flipkart 在路由解析之前 節省了大量的主線程空閑時間(在 3G 網絡下的低性能手機下)。
上面:沒有使用 proload 加載,下面:使用 preload 加載
Chrome 數據保護程序團隊發現,對于那些可以在腳本和 CSS 樣式表上使用 preload 的頁面,發現頁面首次繪制時間獲得平均 12% 的速度提升。
對于 prefetch(預讀取),它被廣泛使用,在 Google 我們仍用它來預讀取一些可以加快 搜索結果頁面 的渲染的關鍵資源。
Preload 在大型網站中都有很好運用,你可以在本文后面找到更多這些安全。 在此之前,讓我們深入了解網絡堆棧如何實際處理 預加載(prefetch)與預讀取(prefetch)。
何時使用 和 ?提示:preload 加載資源一般是當前頁面需要的,prefetch 一般是其它頁面有可能用到的資源。
preload 是告訴瀏覽器預先請求當前頁面需要的資源(關鍵的腳本,字體,主要圖片等)。
prefetch 應用場景稍微又些不同 —— 用戶將來可能跳轉到其它頁面需要使用到的資源。如果 A 頁面發起一個 B 頁面的 prefetch 請求,這個資源獲取過程和導航請求可能是同步進行的,而如果我們用 preload 的話,頁面 A 離開時它會立即停止。
在 preload 和 prefetch 之間,我們對當前頁面或即將跳轉的頁面在所需主要資源的問題有了一個解決方案。
和 的緩存行為當資源被 preload 或者 prefetch 后,會從網絡堆棧傳輸到 HTTP 緩存并進入渲染器的內存緩存。 如果資源可以被緩存(例如,存在有效的 cache-control 和 max-age),它將存儲在 HTTP 緩存中,可用于當前和未來的會話。 如果資源不可緩存,則不會將其存儲在 HTTP 緩存中。 相反,它會被緩存到內存緩存中并保持不變直到它被使用。
Chrome 的網絡棧中是如何處理 preload 和 prefetch 的優先級?下面是在 Blink 內核的 Chrome 46 及更高版本中不同資源的加載優先級情況著作權歸作者所有。
preload 用 “as” 或者用 “type” 屬性來表示他們請求資源的優先級(比如說 preload 使用 as="style" 屬性將獲得最高的優先級)。沒有 “as” 屬性的將被看作異步請求,“Early”意味著在所有未被預加載的圖片請求之前被請求(“late”意味著之后)
我們來談一下這張表。
腳本根據它們在文件中的位置是否異步、延遲或阻塞獲得不同的優先級:
網絡在第一個圖片資源之前阻塞的腳本在網絡優先級中是中級
網絡在第一個圖片資源之后阻塞的腳本在網絡優先級中是低級
異步/延遲/插入的腳本(無論在什么位置)在網絡優先級中是很低級
圖像在可視窗口中比不在視口中的圖像(具有更高的優先級,因此在某種程度上, Chrome 將會盡量懶加載這些不在視口中的圖片。 較低優先級的圖片出現在視口中時,該圖片的優先級就會得到提升(但是注意已經在布局完成后的圖片優先級不會在更改)。
使用“as”屬性預加載的資源將具有與它們請求的資源類型相同的資源優先級。 例如,preload as =“style”將獲得最高優先級,而as =“script”將獲得低優先級或中優先級。 這些資源也遵循相同的CSP策略(例如腳本受 script-src 約束)。
不帶 “as” 屬性的 preload 的優先級將會等同于異步請求。
如果你想了解各種資源加載時的優先級屬性,從開發者工具的 Timeline/Performance 區域的 Network 區域都能看到相關信息:
在 Network 面板下的 “Priority” 部分
當頁面 preload 已經在 Service Worker 緩存及 HTTP 緩存中的資源時會發生什么?這各情況來說是比較少的,但通常來說,會是比較好的情況 —— 如果資源沒有超出 HTTP 緩存時間或者 Service Worker 沒有主動重新發起請求,那么瀏覽器就不會再去請求這個資源了。
如果資源在 HTTP 緩存中(在SW緩存和網絡之間),那么 preload 會從相同的資源中獲得緩存命中。
這種加載方式會浪費用戶的帶寬嗎使用 preload 或 prefetch,可能會浪費用戶的帶寬,特別是在資源沒有緩存的情況下。
沒有用到的 preload 資源在 Chrome 的 console 里會在 onload 事件 3s 后發生警告。
這個警告的原因是,你可能正在使用preload來嘗試為其他資源預加載并緩存以提高性能,但是如果這些預加載的資源沒有被使用,那么你就在毫無理由地做額外的工作。在移動設備上,這相當于浪費用戶的流量,所以要注意預加載的內容。
什么情況會導致二次獲取?preload 和 prefetch 是很簡單的工具,你很容易不小心二次獲取。
不要用 “prefetch” 作為 “preload” 的后備方案 ,它們適用于不同的場景,常常會導致不符合預期的二次獲取。使用 preload 來獲取當前需要任務否則使用 prefetch 來獲取將來的任務,不要一起用。
對 preload 使用 “as” 屬性,不然將不會從中獲益。
如果在指定要 preload 的內容(例如腳本)時未提供有效的“as”,則最終將獲取兩次。
preload 字體不帶 crossorigin 也將會二次獲取, 確保在使用 preload 獲取字體時添加crossorigin 屬性,否則將二次下載。 他這個請求使用匿名的跨域模式。 即使字體與頁面位于同個域 下,也建議使用。也適用于其他域名的獲取(比如說默認的異步獲取)。
最后,雖然它不會導致兩次獲取,但這通常是一個很好的建議:
不要所有的請求資源都加 preload,用 preload 來告訴瀏覽器一些很被需要的資源,以便讓它提早獲取它們。
我應當在頁面頭部所有的資源都加上 preload?這是工具的一個很好的例子,而不是規則。 preload 的文件數量取決于加載其他資源時網絡內容、用戶的帶寬和其他網絡狀況。
盡早 preload 頁面中可能需要的文件,對于腳本,preload 你的關鍵模塊是很好的,因為它將獲取與執行分開,而僅僅使用 不會這樣做,因為它會阻止窗口的 onload 事件。你可以 preload 圖像、樣式、字體和媒體。最重要的是,作為一名頁面作者,你可以更好地控制提前獲取頁面所需要的信息。
prefetch 是否具有你應該注意的任何魔法屬性? 是的,在 Chrome 中,如果用戶導航離開一個頁面,而對其他頁面的預取請求仍在進行中,這些請求將不會被終止。
此外,無論資源的可緩存性如何,prefetch 請求在未指定的網絡堆棧緩存中至少保存 5 分鐘。
我在 JS 中使用自定義的 “preload”,它跟原本的 rel="preload" 或者 preload 頭部有什么不同?preload 解耦從 JS 處理和執行中獲取資源。 因此,preload 在標記中聲明以被 Chrome preload 掃描器掃描。 這意味著在許多情況下,在 HTML 解析器甚至到達標簽之前,將獲取預加載(具有指示的優先級),這使它比自定義預加載實現更強大。
不是可以用 HTTP/2 的服務器推送來代替 preload 嗎?當你知道資源的精確加載順序時使用推送,并讓 service worker 攔截可能導致再次推送緩存資源的請求。 使用 preload 可以使資源的開始下載時間更接近初始請求 - 這對所有的資源獲取都有用。
我們假設瀏覽器正在加載一個頁面,頁面中有個 CSS 文件,CSS 文件又引用一個字體庫,對于這樣的場景,
若使用 HTTP/2 PUSH,當服務端獲取到 HTML 文件后,知道以后客戶端會需要字體文件,它就立即主動地推送這個文件給客戶端,如下圖:
而對于 preload,服務端就不會主動地推送字體文件,在瀏覽器獲取到頁面之后發現 preload 字體才會去獲取,如下圖:
雖然推送很有效,但它不像 preload 那樣對所有的情況都適應。
推送不能用于第三方資源的內容,通過立即發送資源,它還有效地縮短瀏覽器自身的資源優先級情況。在你明確的知道在做什么時,這應該會提高你的應用性能,如果不是很清晰的話,你也許會損失掉部分的性能。
peload 請求頭是什么?它與 preload 標簽相比如何?它與 HTTP/2 服務器推送有什么關系?與其他類型的鏈接一樣,preload 鏈接即可以使用 HTML標記 或 HTTP標頭。 在任何一種情況下,preload 鏈接都會指示瀏覽器開始將資源加載到內存緩存中,這表明該頁面有很高可能性使用該資源,并且不希望等待預加載掃描程序或解析程序發現它。
當金融時報在它們的網站使用 preload HTTP 頭時,他們節約了大約 1s 的顯示片頭圖片時間。
1: 沒有使用 preload 2:使用了 preload
你可以使用任何一種形式提供 preload 鏈接,但是你應該知道一個重要區別:如規范所允許的,許多服務器在遇到 HTTP 頭的 preload 鏈接時會觸發 HTTP/2 服務器推送。 HTTP/2 推送的性能影響不同于普通的預加載,所以你要確保沒有發起不必要的推送。
你可以使用 preload 標簽來代替 preload 頭以避免不必要的推送,或者在你的 HTTP 頭上加一個 “nopush” 屬性。
如何判斷 的支持情況?以下的代碼段可以判斷 支持情況:
const preloadSupported = () => { const link = document.createElement("link"); const relList = link.relList; if (!relList || !relList.supports) return false; return relList.supports("preload"); };
FilamentGroup 也有一個 preload 檢測器 ,作為他們的異步 CSS 加載庫 loadCSS 的一部分。
可以使用 preload 讓CSS樣式立即生效嗎?當然可以,preload 支持基于異步加載的標記,使用 的樣式表可以使用 onload 事件立即應用于當前文檔:
preload 還被哪些網站廣泛的應用?
根據 HTTPArchive,大多數使用 的網站使用它來預加載Web字體,包括 Teen Vogue 和前面提到的 Shopify:
而 LifeHacker 和 JCPenny 等其他熱門網站使用它來異步加載CSS(通過Filament Group loadCSS):
然后,有越來越多的漸進式 Web 應用程序(如 Twitter.com mobile、Flipkart 和Housing)使用它來預加載當前導航所需的腳本(使用PRPL等模式)
其基本思想是以高粒度維護工件(而不是整體捆綁),所以任何應用都可以按需加載依賴或者預加載資源并放在緩存中。
當前瀏覽器對 preload 和 Prefetch 的支持程序如何根據 CanIUse,約 50% 的支持度, 約 71%。
相關閱讀Preload?—?what is it good for??—?Yoav Weiss
A study by the Chrome Data Saver team
Planning for performance?—?Sam Saccone
Webpack plugin for auto-wiring up
What is preload, prefetch and preconnect??—?KeyCDN
Web Fonts preloaded by Zach Leat
HTTP Caching: cache-control by Ilya Grigorik
代碼部署后可能存在的BUG沒法實時知道,事后為了解決這些BUG,花了大量的時間進行log 調試,這邊順便給大家推薦一個好用的BUG監控工具 Fundebug。
你的點贊是我持續分享好東西的動力,歡迎點贊!
交流干貨系列文章匯總如下,覺得不錯點個Star,歡迎 加群 互相學習。
https://github.com/qq44924588...
我是小智,公眾號「大遷世界」作者,對前端技術保持學習愛好者。我會經常分享自己所學所看的干貨,在進階的路上,共勉!
關注公眾號,后臺回復福利,即可看到福利,你懂的。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/103430.html
摘要:當然并不是所有的頁面需要用到的外部域名都需要做這樣的域名解析,瀏覽器默認會解析超鏈接屬性的里面的域名,并且你的網站域名還不能是,如果是,則需要設置請求頭或加入一段強制開啟域名解析的標簽。 廢話:異步加載和預加載一直都是前端優化必備技能之一,今天我們就來深度解析一下常用的幾個關鍵點。 異步加載 廢話不多說,任何長篇大論的教程都抵不過一張清晰明了的高清大圖來得好: showImg(http...
摘要:當然并不是所有的頁面需要用到的外部域名都需要做這樣的域名解析,瀏覽器默認會解析超鏈接屬性的里面的域名,并且你的網站域名還不能是,如果是,則需要設置請求頭或加入一段強制開啟域名解析的標簽。 廢話:異步加載和預加載一直都是前端優化必備技能之一,今天我們就來深度解析一下常用的幾個關鍵點。 異步加載 廢話不多說,任何長篇大論的教程都抵不過一張清晰明了的高清大圖來得好: showImg(http...
摘要:和可以用來指定資源是最高優先級的。如果用戶進入指定的鏈接,隱藏的這個頁面就會進入馬上進入用戶的視線。微軟最近也宣布會讓在上用類似的技術。 預加載 現在的網絡情況雖然很樂觀,但是 defer和async 當瀏覽器碰到 script 腳本的時候: 沒有 defer 或 async,瀏覽器會立即加載并執行指定的腳本,立即指的是在渲染該 script 標簽之下的文檔元素之前,也就是說不等待后...
摘要:之前分享過幾篇關于技術棧的原創文章解析前端架構學習復雜場景數據設計干貨總結打造單頁應用一個項目理解最前沿技術棧真諦一個工程實例今天進一步剖析一個實際案例移動網頁版。目前面臨的問題在于提高產品的各方面性能體驗。 之前分享過幾篇關于React技術棧的原創文章: 解析Twitter前端架構 學習復雜場景數據設計 React Conf 2017 干貨總結1: React + ES next ...
摘要:當瀏覽器發現時,就會下載,解析,然后更新,這時會引起一次重繪。這個過程中,有兩個非常嚴重的問題。如果你對異步加載的方案感興趣,歡迎留言與我討論擴展閱讀瀏覽器的工作原理關于你應該知道些什么,和它們在之中的優先級 我來填坑了,CSS篇終于寫出來了,如果你沒看過前面的JS篇,可以在這里觀看。 眾所周知,CSS的加載會阻塞瀏覽器渲染或是引起瀏覽器重繪,目前業界普遍推薦把CSS放到中,防止在CS...
閱讀 4168·2023-04-26 02:40
閱讀 2661·2023-04-26 02:31
閱讀 2753·2021-11-15 18:08
閱讀 572·2021-11-12 10:36
閱讀 1433·2021-09-30 09:57
閱讀 5204·2021-09-22 15:31
閱讀 2631·2019-08-30 14:17
閱讀 1278·2019-08-30 12:58