在webpack中使用prefetch/preload
這是什麼?
這種“資源提示” 告訴瀏覽器這是一個在未來 可能 使用到的資源。
瀏覽器通常會在空閒狀態取得這些資源,在取得資源之後擱在HTTP快取以便於實現將來的請求。如果有多個‘預請求提示’則會在瀏覽器空閒時排隊執行。當瀏覽器離開空閒狀態時正好在‘預請求’資源,那麼瀏覽器會取消任何正在進行中的請求(同時會將部分響應資料放置在快取中,而在Header中繼續使用Content-Range欄位 )並停止處理‘預請求’佇列。
總之:在閒置時獲取資源
這是什麼?
這種“資源提示” 告訴瀏覽器這是一種在這次導航中必須的資源,只是會在之後才會被使用, chrome甚至會在資源載入後3秒沒有被使用時列印一個警告
瀏覽器通常以中等優先順序(非佈局阻塞)獲取此資源。
總之:正常獲取,及早發現
為什麼這有用?
預載入用於更早地發現資源並避免發起類似瀑布一樣的請求。 它可以將頁面載入降低到2次往返(1. HTML,2。所有其他資源)。 使用它不會花費額外的頻寬。
預請求用於使用瀏覽器的空閒時間來加速將來的導航。 當用戶未執行預期的未來導航時,使用它可能會花費額外的頻寬。
程式碼分割
我們假設您使用webpack構建龐大的應用程式,並通過import()來使用按需載入僅載入使用者當前所需的部分。
例如,我們有一個HomePage,其中包含一個LoginButton,這個按鈕用於開啟一個登入模態框(LoginModal)。 登入之後會跳轉到DashboardPage——可能包含其他按鈕,但這些按鈕不太常見。
為了獲得更好的使用者體驗,你在LoginButton那裡使用import("LoginModal") 來保持主頁的體積達到最小。與之類似的,LoginModal包含import("DashboardPage")
現在,這個示例程式被拆分為至少3塊:home-chunk,login-chunk,dashboard-chunk。 在初始載入時,只需要載入home-chunk,這會產生很好的使用者體驗。 但是當用戶單擊LoginButton時,在LoginModal開啟之前會有一段延遲,因為需要載入應用程式的這一部分。 DashboardPage與之類似。
在webpack中使用預請求
新的預請求功能可以改善這個工作流程。 並且這非常容易。
在LoginButton處,把import("LoginModal") 改成 import(/ webpackPrefetch: true / "LoginModal")
同樣的把 import("DashboardPage") 改成import(/ webpackPrefetch: true / "DashboardPage")
這將告訴webpack在父塊完成載入時預取(在瀏覽器空閒時間內)這個按需載入的模組。 在這個例子中:當home-chunk完成載入時,將login-chunk新增到預取佇列。 當login-chunk完成載入(實際載入,而不是預取)時,將dashboard-chunk新增到預取佇列。
假設home-chunk是一個入口,那麼它將會被新增到html檔案裡。 login-chunk是一個按需載入模組,因此一旦login-chunk載入完成,webpack執行時將負責注入。
用這種方式將會提升使用者體驗:
當用戶訪問HomePage時。 這時的使用者體驗和效能與以前一樣。一旦HomePage完成載入,瀏覽器就會進入空閒狀態並開始在後臺獲取login-chunk。而使用者並不會注意到這一點。 假設使用者需要一些時間來查詢LoginButton,那麼預請求將在使用者單擊按鈕之前完成。 當用戶單擊該按鈕時,login-chunk已經位於HTTP快取中,瀏覽器僅會花費最少的時間來命中快取中的資料,那麼使用者將立即看到LoginModal。 同時,webpack執行時將dashboard-chunk新增到預取佇列,因此登入後加載dashboard-chunk也不需要額外的時間。
請注意,使用者可能並不總是具有這種即時LoginModal體驗。 對LoginButton來說,有許多因素會使chunk重新載入以至於延遲:慢速網路,使用者快速點選,在頻寬有限的裝置上禁用預取,沒有預取瀏覽器支援,塊的執行速度非常慢,......
在webpack中使用預載入
與import(/ webpackPrefetch:true /“...”)類似,也可以使用import(/ webpackPreload:true /“...”)。 與預取相比,這有很多不同之處:
-
預載入的塊與父塊並行載入。預請求的塊在父塊完成之後開始載入。
-
預載入的塊具有中等優先順序並立即下載。 預請求的塊在瀏覽器空閒時間下載。
-
預載入的塊會被父塊立即請求。 預請求的塊可能會在將來的任何時間請求
-
瀏覽器支援是不同的。
preload這種特性的用例很少見。 如果模組總是立即import()某些內容,則可以使用它。 如果一個元件依賴一個單獨塊中的大型庫,那麼這是有意義的。 示例:ChartComponent使用大的ChartingLibrary。 它在使用時顯示一個LoadingIndicator並立即匯入(/ webpackPreload:true /“ChartingLibrary”)。 當請求使用ChartComponent的頁面時,也會通過請求圖表庫塊。 假設頁面塊較小並且完成得更快,則將使用LoadingIndicator顯示頁面,直到已經請求的圖表庫塊完成為止。 這將提供一點載入時間,因為它只需要一次往返而不是兩次。 特別是在高延遲環境中。
如果使用webpackPreload不當實際上會損害效能,因此要小心使用它。
在考慮預載入與預請求時,您可能需要預請。 但是要注意:此宣告與webpack import()有關。 在HTML頁面中,您可能需要預載入。
多個預載入的塊
您可以將webpackPrefetch標誌新增到任意數量的import(),但請注意所有預取的塊都會爭奪頻寬。 它們實際上是排隊的,當用戶請求它時,真正使用的塊可能不會被預取。
當所有塊被請求的可能性相同時,這不是一個大問題。 但是當某些塊比其他塊被訪問的可能性更大時,您可能想要控制預取的順序。
幸運的是,我們可以讓你滿意。 (注意這是一個高階用例。)
您可以傳遞數字作為值,而不是使用webpackPrefetch:true。 webpack將按您指定的順序預取塊。比如:webpackPrefetch:42將在webpackPrefetch:1之前被預取,它將在webpackPrefetch:true之前被預取,它將在webpackPrefetch:-99999(如z-order)之前被預取。 實際上,true等價於為0。
webpackPreload與之類似,但我不認為您會需要它
常見問題
如果多個import()請求相同的塊並且其中一些被預取/預載入怎麼辦?預載入勝過預取。 在同一類別中,更高優先順序獲勝。
如果瀏覽器不支援預取/預載入怎麼辦?它會被瀏覽器忽略。 webpack不會嘗試做任何後備。 不管怎樣這都是一個暗示,所以即使是支援它的瀏覽器也可能會忽略它,如果他們感覺如此。
Prefetch/preload在入口點中不起作用。 有什麼問題?webpack執行時只負責按需載入的塊的Prefetch/preload。 當在entry chunk中使用預取/預載入時,html會新增標記到HTML。 stats.json在entrypoints[].childAssets中提供了資訊
為什麼不在每個import()上使用prefetch / preload?你浪費了很多頻寬。 有選擇地將它用於很可能被訪問的import()也更有益。 不要浪費頻寬。
我不需要/想要這個功能。 不使用它的成本是多少?只有在您的一個按需載入的塊中使用此功能時,才會新增執行時程式碼。 因此,當不使用它時,您不必支付任何開銷。
我已經在import()上有一個comment了。 我可以新增多個嗎?是的,要麼用單獨的comment分開,要麼在單獨的評論中:
import(/* webpackChunkName: "test", webpackPrefetch: true */"LoginModal")// orimport(/* webpackChunkName: "test" *//* webpackPrefetch: true */"LoginModal")// spacing optional
我使用rollup構建我的庫,並使用import(), 我的庫中使用webpack的使用者可以從prefetch中獲益嗎?是的,您可以將webpack魔術註釋新增到import()中,rollup將保留註釋。 當使用webpack構建它的結果時,它將使用註釋。 如果沒有使用webpack構建,評論將被minimizers刪除。
我不確定是否為特定import()新增預取可以提高效能。 我應該加嗎?最好的衡量標準。 A / B測試。 這裡沒有一般建議。 它取決於使用者訪問此應用程式路徑的概率。
我已經有一個service worker,可以在載入時快取整個應用程式。 使用預取對我有意義嗎?這取決於您的應用程式。 通常,這種service worker無順序載入應用程式的所有資產,而預取允許指定順序並依賴於使用者在應用程式中的實際位置。 預取也可以提高頻寬效率,並且只能在瀏覽器空閒時下載。 與第一次使用者導航發生時相比,測量在低頻寬環境中下載整個應用程式所需的時間。 在大型應用程式中,使用預取代替是有意義的。
我想將初始頁面載入拆分為關鍵資源和非關鍵資源,並按此順序載入它們。 預載入有幫助嗎?是的,您可以將關鍵資源放入入口點,將非關鍵資源放在import(/webpackPreload:true/)之後。 注意不要忘記為entry chunk 新增(在子標記之前)。
與許多其他大型開源產品不同,webpack沒有大公司的支援。 該發展專案由捐贈資助。 如果你依賴網路包,請考慮捐贈...(問你的老闆!)
特別感謝這些贊助商:(前5名)