Preload與Prefetch的區別以及webpack專案中如何優化
preload 與prefetch 的區別
-
preload是一個宣告式 fetch,可以強制瀏覽器在不阻塞 document 的 onload 事件的情況下請求資源。
preload 顧名思義就是一種預載入的方式,它通過宣告向瀏覽器宣告一個需要提交載入的資源,當資源真正被使用的時候立即執行,就無需等待網路的消耗。
-
prefetch告訴瀏覽器這個資源將來可能需要,但是什麼時間載入這個資源是由瀏覽器來決定的。
若能預測到使用者的行為,比如懶載入,點選到其它頁面等則相當於提前預載入了需要的資源。
使用方法:
通過 Link 標籤進行建立:
<link rel="preload" href="/path/to/style.css" as="style">
在 HTTP 響應頭中加上 preload 欄位:
Link: <https://example.com/other/styles.css>; rel=preload; as=style
這種方式比通過 Link 方式載入資源方式更快,請求在返回還沒到解析頁面的時候就已經開始預載入資源了。
prefetch 預判載入與preload 使用方法是一樣的
和的快取行為
當資源被 preload 或者 prefetch 後,會從網路堆疊傳輸到 HTTP 快取並進入渲染器的記憶體快取。 如果資源可以被快取(例如,存在有效的 cache-control 和 max-age),它將儲存在 HTTP 快取中,可用於當前和未來的會話。 如果資源不可快取,則不會將其儲存在 HTTP 快取中。 相反,它會被快取到記憶體快取中並保持不變直到它被使用。
副作用
正確使用 preload/prefetch 不會造成二次下載,也就說:當頁面上使用到這個資源時候 preload 資源還沒下載完,這時候不會造成二次下載,會等待第一次下載並執行指令碼。
對於preload 來說,一旦頁面關閉了,它就會立即停止 preload 獲取資源,而對於prefetch 資源,即使頁面關閉,prefetch 發起的請求仍會進行不會中斷。
preload 和 prefetch 的優先順序、
preload 用 “as” 或者用 “type” 屬性來表示他們請求資源的優先順序(比如說 preload 使用 as=”style” 屬性將獲得最高的優先順序)。沒有 “as” 屬性的將被看作非同步請求,“Early”意味著在所有未被預載入的圖片請求之前被請求(“late”意味著之後)
例如,preload as =“style”將獲得最高優先順序,而as =“script”將獲得低優先順序或中優先順序。 這些資源也遵循相同的CSP策略(例如指令碼受 script-src 約束)。
下面是在 Blink 核心的 Chrome 46 及更高版本中不同資源的載入優先順序情況著作權歸作者所有。
從圖中可以看出:(以 Blink 為例)
-
HTML/CSS 資源,其優先順序是最高的
-
font 字型資源,優先順序分別為 Highest/High
-
圖片資源,如果出現在視口中,則優先順序為 High,否則為 Low
而 script 指令碼資源就比較特殊,優先順序不一,指令碼根據它們在檔案中的位置是否非同步、延遲或阻塞獲得不同的優先順序:
-
網路在第一個圖片資源之前阻塞的指令碼在網路優先順序中是 High
-
網路在第一個圖片資源之後阻塞的指令碼在網路優先順序中是 Medium
-
非同步/延遲/插入的指令碼(無論在什麼位置)在網路優先順序中是 Low
當頁面 preload 已經在 Service Worker 快取及 HTTP 快取中的資源時會發生什麼?
這各情況來說是比較少的,但通常來說,會是比較好的情況 —— 如果資源沒有超出 HTTP 快取時間或者 Service Worker 沒有主動重新發起請求,那麼瀏覽器就不會再去請求這個資源了。
如果資源在 HTTP 快取中(在SW快取和網路之間),那麼 preload 會從相同的資源中獲得快取命中。
使用 preload 或 prefetch,可能會浪費使用者的頻寬,特別是在資源沒有快取的情況下。
沒有用到的 preload 資源在 Chrome 的 console 裡會在 onload 事件 3s 後發生警告。
webpack優化之preload和prefetch
單頁面應用由於頁面過多,可能會導致程式碼體積過大,從而使得首頁開啟速度過慢。所以切分程式碼,優化首屏開啟速度尤為重要。
但是所有的技術手段都不是完美的。當我們切割程式碼後,首屏的js檔案體積減少了好多。但是也有一個突出的問題:
那就是當跳轉其他頁面的時候,需要下載相應頁面的js檔案,這就導致體驗極其不好,每一次點選訪問新頁面都要等待js檔案下載,然後再去請求介面獲取資料。頻繁出現loading動畫的體驗真的不好
所以如果我們在進入首頁後,在瀏覽器的空閒時間提前下好使用者可能會點選頁面的js檔案,這樣首屏的js檔案大小得到了控制,而且再點選新頁面的時候,相關的js檔案已經下載好了,就不再會出現loading動畫。
動態引入js檔案,實現code-splitting,減少首屏開啟時間
按引入情況載入,只需添加註釋即可
-
程式碼分割註釋:/*webpackChunkName: 'mp-supports'*/
-
prefetch註釋:/* webpackPrefetch: true */
更多的,可以檢視 webpack 註釋黑魔法:https://webpack.js.org/api/module-methods/#magic-comments
使用案例
const{default:lodash}=awaitimport(/*webpackChunkName:"lodash"*//*webpackPrefetch:true*/'lodash'); //Multiplepossibletargets import( /*webpackInclude:/\.json$/*/ /*webpackExclude:/\.noimport\.json$/*/ /*webpackChunkName:"my-chunk-name"*/ /*webpackMode:"lazy"*/ /*webpackPrefetch:true*/ /*webpackPreload:true*/ `./locale/${language}` );
原來還可以疊羅漢的
react專案
//程式碼分割後的react元件 constDemo=asyncComponent(()=>import( /*webpackChunkName:'mp-supports'*/ './views/Brand' )) //路由引入 <Routepath="/"component={App}> <Routepath="/brand"component={Demo}/> </Route>
首頁元件的生命週期:
/在介面取的資料後,進行prefetch componentDidUpdate({topics}){ if(topics.length===0&&this.props.topics.length>0){ //實行prefetch,注意只有webpack4版本才支援prefetch功能。 import( /*webpackPrefetch:true*/ /*webpackChunkName:'topic'*/ "../topic" ) } }
參考文章:
3 Code Splitting Patterns For VueJS and Webpackhttps://medium.com/js-dojo/3-code-splitting-patterns-for-vuejs-and-webpack-b8fff1ea0ba4
使用 Proload/Prefetch 優化你的應用https://github.com/happylindz/blog/issues/17
Web 效能優化:Preload,Prefetch的使用及在 Chrome 中的優先順序https://segmentfault.com/a/1190000018828048
webpack 中,webpackPrefetch、webpackPreload 和 webpackChunkName 的區別是什麼?https://www.cnblogs.com/skychx/p/webpack-webpackChunkName-webpackPreload-webpackPreload.html
轉載本站文章《Preload與Prefetch的區別以及webpack專案中如何優化》,
請註明出處:https://www.zhoulujun.cn/html/webfront/SGML/html5/2020_0702_8505.html