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

豪賽因.吉爾德 (Houssein Djirdeh)
Houssein Djirdeh
傑瑞米.瓦格納 (Jeremy Wagner)
Jeremy Wagner

沒有人喜歡等待。 在網站載入時間超過 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 的常用架構都提供抽象化機制,比起自行深入瞭解設定,延遲載入更為簡單。