在過去的 15 年裡,JavaScript 生態系統迅速擴展,引入了無數工具使開發變得更加容易。但這些工具是有代價的:增加捆綁包的大小。事實上,HTTP Archive 的數據顯示,每頁平均傳輸的 JavaScript 量已從 2010 年的 90 KB 激增至 2024 年的 650 KB(來源)。
儘管壓縮技術的採用率不斷提高並且取得了進步,但這一趨勢並沒有顯示出放緩的跡象。隨著我們不斷添加功能,挑戰仍然存在:我們如何減少 JavaScript 的數量?
奇怪的是,解決方案既簡單又困難。最簡單的部分是專案層級的調整,可以快速取得成果。困難的部分是產生持久的影響,這需要社區範圍內的改變來改善捆綁器、庫和工具。
本文著重於您的專案的可行改進,涵蓋:
未來的文章將討論我們可以做出的生態系統範圍內的改進,但現在,讓我們解決這些因素如何導致捆綁包膨脹 - 以及如何管理它們。
JavaScript 是現代網路互動背後的引擎,但它不是免費的。 JavaScript 是瀏覽器必須處理的計算成本最高的資源。它通常是決定頁面感覺快還是慢的瓶頸,因為臃腫的套件會阻止渲染並降低整體效能。
JavaScript 套件越大,載入、解析、編譯和執行所需的時間就越長。這會延遲其他一切 - 例如顯示內容或讓使用者與頁面互動。對於使用具有光纖連接的高階筆記型電腦的人來說,這可能是一個小煩惱。但對於使用低功率手機或不穩定網路的人來說,這可能是完全留在或離開您的網站的區別。
減少 JavaScript 套件大小的第一步是 Tree Shaking(或「死程式碼消除」),大多數的捆綁器都是開箱即用。但所有捆綁商都是平等的嗎?
JavaScript 中的捆綁已經取得了長足的進步——從手動串聯和任務運行器到複雜的捆綁器。如今,捆綁器效能是一個關鍵焦點,開發人員優先考慮更快的建置。然而,建造速度並不是一切。同樣重要的是它們產生的捆綁包的大小,因為較小的捆綁包意味著用戶的載入時間更快。
為了尋求更好的效能,我們已經從使用 JavaScript 編寫捆綁器轉向 Rust 和 Go 等語言。此切換需要從頭開始編寫它們,因此舊捆綁器中存在的每個功能和最佳化都必須重新實現。從長遠來看,這可能會得到回報。然而,從短期來看,這意味著它們缺少 JavaScript 捆綁器多年來開發的一些功能,例如良好的 tree shake。這正是可以幫助我們最小化捆綁包大小的功能。
當然,空談是廉價的,所以讓我們看看數字,好嗎?
讓我們比較八個流行的庫,並將它們與七個流行的捆綁器捆綁在一起。為了保持公平,我使用了:
您可以查看基準設定儲存庫以取得確切的配置。
經過測試的捆綁器:
請注意,在撰寫本文時,Rolldown 仍處於 alpha 階段,因此它處於劣勢,隨著時間的推移,其結果可能會有所改善。
測試過的函式庫:
這些函式庫的大小和功能各不相同 - 有些程式庫幾乎可以像獨立應用程式一樣運作。
讓我們從建造速度開始,因為這是開發人員似乎非常關心的事情。將所有這些庫捆綁在一起時,esbuild 是獲勝者,其構建時間為 192 毫秒。與最慢的建置時間 7.23 秒相比,快了 37 倍以上。
根據這些結果,我們可以將捆綁器分為三類:
差異非常明顯。例如,Rolldown 和 Rspack 分別比舊版 Rollup 和 webpack 快 11.5 倍和 3.3 倍,同時保持理論上的向後相容性。切換到這些較新的捆綁器可以顯著提高大型專案的生產力。
就輸出大小而言,差異並不像建置時間那麼大,但它們仍然很重要。
將所有八個庫捆綁在一起時,Vite 是獲勝者,輸出大小為 2087 KiB。與最大輸出大小 2576 KiB 相比,輸出小了 23.5% 以上。
輸出大小的 23.5% 差異是巨大的:在較慢的 3G 連接下,最小的包可能需要大約 5.7 秒才能下載,而最大的包可能需要大約 7 秒。解析和執行時間也會隨著套件的大小而變化,因此現實世界的差異可能更加明顯。
根據這些結果,我們可以將捆綁器輸出再次分為三類:
聚合結果並不能描繪出全貌,因為您不太可能在專案中使用上面列出的所有函式庫。更有趣的是這些捆綁器如何處理各個庫。
對於像chart.js和mobx這樣的函式庫,捆綁器的選擇會大大影響輸出大小,差異達到70%。這凸顯了使用特定相依性測試捆綁程序的重要性。在大多數其他情況下,差異要小得多,約為 20-30%。
此外,雖然 webpack 總體排名居中,但在 8 個案例中,有 6 個案例表現最好。然而,由於在捆綁handsontable和chart.js時它的表現要差得多,所以它最終還是這樣。這意味著,根據您使用的庫,webpack 可能是一個不錯的選擇。
另一方面,我們有 Rolldown。它在 8 個案例中的 7 個案例中表現最差(請記住,它仍處於 alpha 狀態)。
Rspack 也是一個類似的故事。雖然它的性能比 Rolldown 更好,但它仍然產生了比其他捆綁器大得多的捆綁包。
如果您正在考慮遷移到較新的捆綁程序,使用您使用的庫進行測試,看看更快的構建速度是否不會以增加輸出大小為代價。
如圖所示,較新的捆綁器速度更快,但可能會產生更大的捆綁包。從較舊的捆綁程式遷移時,不僅要比較建置時間,還要比較產生的捆綁包大小。您可能會發現自己用更快的構建來換取更大的捆綁包。
例如,在 Angular 從 webpack 切換到 esbuild 後,一些開發人員報告說,空的 Angular 應用程式的大小增加了約 20KB。這完美地突出了構建速度與捆綁包大小的權衡。
這並不是說您不應該關注構建速度,因為它對於開發人員的生產力和幸福感很重要。 CI 建置時間和合併程式碼所需的時間之間也存在相關性。
選擇捆綁器時,首先查看它提供的功能。然後目標是建造速度和包大小之間的平衡。選擇可以在您方便的時間內生產盡可能最小的捆綁包的捆綁包的捆綁商。
測試項目中的一些代表性庫。如果您的依賴項構成了程式碼庫的大部分,那麼您在這些基準測試中看到的差異可以很好地預測您的情況。
我們清單中的下一個是外部函式庫,它們通常構成 JavaScript 套件的大部分。在我開發過的許多(如果不是大多數)應用程式中,它們佔據了捆綁包大小的大部分。這就是為什麼明智地選擇(和使用)它們如此重要。
我們中的許多人都安裝了 lodash、axios 或 moment 等庫,只是為了使用單一功能 - 導致應用程式臃腫。這些庫很棒並且具有重要的歷史意義,但隨著它們變得越來越流行,更輕的替代品被創建,並且它們的一些功能被添加到語言本身中。
我們可以利用這一點。我可以列出這些庫的本機 API 或更新且更小的替代方案,但已經有很多文章對此進行了介紹。還有很多其他函式庫,不可能全部涵蓋。
這就是為什麼我只會給你一個一般性建議,讓你看看你使用的庫,看看是否可以刪除它們或用本機 API 或更小的替代品替換它們。您可能不需要 * 網站是一個很好的入門資源。
預設情況下,大多數程式庫並未針對大小進行最佳化,但有些程式庫提供特殊的安裝路徑或部分建置。即使在我們測試的庫中,chart.js、handsontable 和 ckeditor5 也提供了一種透過僅包含您需要的部分來減小庫大小的方法。讓我們以 ckeditor5 為例。
預設安裝路徑導致捆綁包大小在 660 到 800 KiB 之間。但是,如果我們使用優化的安裝路徑,捆綁包大小會下降到 603-653 KiB,僅 Rolldown 產生的捆綁包大小約為 750 KiB。大小減少了 7% 到 23%,具體取決於捆綁程序。
另一件事要注意的是重複的依賴關係。這是 JavaScript 應用程式中一個令人驚訝的常見問題。例如,Bluesky 嵌入小工具有兩個版本的 zod 驗證庫。刪除重複項使套件大小減少了約 9%。
此問題通常不會發生,因為您拉取了同一庫的兩個不同版本,而是因為您和外部庫之一依賴同一庫,但版本不同。這通常可以透過更新您所依賴的程式庫來解決。
考慮到所有這些,我們終於可以進入最後一塊拼圖 - 您的專案。您可以採取以下措施來縮小捆綁包並提高效能。
第一步是可見性。如果不了解捆綁包中的內容,縮小捆綁包的大小就變成了一場猜謎遊戲。為此,您可以使用我創建的名為 Sonda 的捆綁分析器和視覺化工具。它適用於上述大多數捆綁程序(Parcel 除外),並準確顯示參與捆綁的各個文件的大小。
您可以先將其安裝到您的專案中並目視檢查捆綁包的各個部分。
一旦您充分了解了捆綁包內的內容並確定了可以優化的部分,您就可以單擊圖表圖塊來查看:
Sonda 也會警告您重複的依賴項,以便您可以快速識別並修復問題的根源。
理想情況下,您不僅應該進行一次性檢查,還應該將持續監控設定為 CI 管道的一部分。追蹤一段時間內的變化,尤其是在大型專案中,可以幫助您防止小變化隨著時間的推移滾雪球般變成嚴重的膨脹。
最快的程式碼是您不發送的程式碼。只要有可能:
如果您無法刪除應用程式的某些部分,請嘗試程式碼分割。程式碼分割可讓您推遲載入應用程式的某些部分,直到需要它們為止,從而縮短初始載入時間。
使用動態 import() 按需載入模組。例如,如果在使用者點擊按鈕之前不需要某個特定功能,則會延遲載入該功能直到那一刻。
現代前端框架支援開箱即用的延遲加載,使將程式碼分割整合到您的工作流程中比以往更容易。
這是一般性建議,但值得重複。遵循最佳實踐,例如:
如果您有興趣讓網路更快或只是學習新事物,您應該考慮加入生態系統效能社群。我們專注於三個主要領域:
我希望這篇文章說明您可以用更少的程式碼提供相同的功能。如果不加以管理,捆綁包大小可能會失控,但即使很小的更改也可以顯著提高效能。
從今天開始:分析您的套件、測試新工具或替換重量級庫。其影響會讓你大吃一驚。
我希望您喜歡這篇文章。如果您有任何問題或意見,或者如果您想了解有關特定主題的更多信息,請在下面的評論中告訴我。如果您想了解有關 JavaScript 性能、捆綁和 tree-shaking 主題的更多信息,您可以在此處關注我或在 BlueSky 上關注我並加入 e18e 社區。
以上是縮小 JavaScript 規模:掌握 Bundler 優化的詳細內容。更多資訊請關注PHP中文網其他相關文章!