利用程式碼分割功能減少 JavaScript 酬載

沒有人喜歡等待。 在網站載入時間超過 3 秒的情況下,超過 50% 的使用者會放棄瀏覽

傳送大型 JavaScript 酬載會大幅影響網站的速度。在應用程式第一頁載入後,請將所有 JavaScript 分割成多個片段,並在開頭只傳送必要的內容,而不要在載入所有 JavaScript 後立即傳送所有 JavaScript 給使用者。

程式碼分割功能的優點為何?

程式碼分割是一種盡可能縮短啟動時間的技術。當啟動時發布的 JavaScript 數量較少,我們可以確保應用程式在這個重要期間盡可能減少主執行緒作業,進而加快互動速度

關於網站體驗核心指標,減少啟動時下載的 JavaScript 酬載,將有助於改善首次輸入延遲時間 (FID)與下次繪製 (INP) 互動的時間。背後的原因是釋出主執行緒,讓應用程式能夠減少 JavaScript 剖析、編譯和執行作業相關的啟動費用,更快回應使用者輸入內容。

視網站的架構而定 (尤其是網站嚴重仰賴用戶端算繪的情況),減少負責轉譯標記的 JavaScript 酬載大小可能會導致最大內容繪製 (LCP) 次數成長時間。如果出現 LCP 資源延遲瀏覽器才偵測到資源,直到用戶端標記完成,或主執行緒忙於轉譯該 LCP 元素為止,就可能發生這種情況。這兩種情況都會延遲網頁的 LCP 時間。

測量

Lighthouse 會在長時間執行網頁上所有 JavaScript 時,顯示失敗的稽核資訊。

Lighthouse 稽核失敗,顯示指令碼執行時間過長。

分割 JavaScript 套件,只在使用者載入應用程式時,只傳送初始路徑所需的程式碼。這樣可以盡量減少需要剖析和編譯的指令碼,進而加快網頁載入時間。

常見的模組組合器 (例如 webpackParcelRollup) 可讓您使用動態匯入來分割套件。舉例來說,下列程式碼片段顯示了在提交表單時觸發的 someFunction 方法範例。

import moduleA from "library";

form.addEventListener("submit", e => {
  e.preventDefault();
  someFunction();
});

const someFunction = () => {
  // uses moduleA
}

在這裡,someFunction 會使用從特定程式庫匯入的模組。如未使用這個模組,您可以修改程式碼區塊,使用動態匯入功能,以便只在使用者提交表單時擷取這個模組。

form.addEventListener("submit", e => {
  e.preventDefault();
  import('library.moduleA')
    .then(module => module.default) // using the default export
    .then(() => someFunction())
    .catch(handleError());
});

const someFunction = () => {
    // uses moduleA
}

組成模組的程式碼不會納入初始套件,而是延遲載入,或只在表單提交後需要提供給使用者。如要進一步提升網頁效能,請預先載入重要區塊以排定優先順序,並提早擷取這些區塊

雖然先前的程式碼片段為簡易範例,但延遲載入第三方依附元件並不是大型應用程式的常見模式。第三方依附元件通常會分割成獨立的廠商套件,由於其更新頻率較低,因此可快取。如要進一步瞭解如何執行這項作業,請參閱 SplitChunksPlugin

使用用戶端架構時,根據路徑或元件層級分割,是延遲載入應用程式不同部分的更簡單。許多使用 Webpack 的常用架構都提供抽象化機制,比起自行深入瞭解設定,延遲載入更為簡單。