1. 程式人生 > 其它 >Preload與Prefetch的區別以及webpack專案中如何優化

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 為例)

  1. HTML/CSS 資源,其優先順序是最高的

  2. font 字型資源,優先順序分別為 Highest/High

  3. 圖片資源,如果出現在視口中,則優先順序為 High,否則為 Low

而 script 指令碼資源就比較特殊,優先順序不一,指令碼根據它們在檔案中的位置是否非同步、延遲或阻塞獲得不同的優先順序:

  1. 網路在第一個圖片資源之前阻塞的指令碼在網路優先順序中是 High

  2. 網路在第一個圖片資源之後阻塞的指令碼在網路優先順序中是 Medium

  3. 非同步/延遲/插入的指令碼(無論在什麼位置)在網路優先順序中是 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