Categories
程式開發

基於 webpack 的應用治理


當前市面上大部分前端應用都是基於 webpack 進行構建,而隨著應用日益龐大,webpack 應用就會出現構建速度慢,構建結果體積大等一系列問題。

一、webpack 應用治理應該從哪個方向入手?

隨著應用的不斷迭代,webpack 應用最常見的兩個問題就是:

  1. 構建速度慢;
  2. 構建體積大。

有一個很簡單的劃分方式,就是以構建(build)為分界線,分成前向治理和後向治理:

  • 前向治理:提升構建速度;
  • 後向治理:保證構建結果質量。

我們的治理方向,就是圍繞前向治理和後向治理。

基於 webpack 的應用治理 1

二、前向治理包含哪些內容?

前向治理的核心概念,就是一個字 `快`,目的就是提升構建速度,市面上大部分 webpack 優化文章都是這一類提升構建速度的文章,所以這裡就簡單介紹一些不錯的實踐

1. 利用 SMP 採集 webpack 數據指標

基於 webpack 的應用治理 2

數據先行,通過 speed-measure-webpack-plugin 採集性能指標,可以得到 webpack 在整個編譯過程中在 loader、plugin 上花費的時間,基於該數據可以專項的進行優化和治理。

2. 開啟緩存

如果通過 SMP 分析得知在 loader 編譯過程耗時較多,那麼可以在核心 loader,例如 babel-loader 中添加緩存。

{
  loader: 'babel-loader',
    options: {
      cacheDirectory: true
    }
}

3. 開啟 happyPack 多線程編譯

如果通過 SMP 分析得知在 loader 編譯過程耗時較多,還可以通過使用 happyPack,開啟多線程編譯,提升開發效率。

4. 使用 dll 技術

dll 可以簡單理解成提前打包,例如 lodash、echarts 等大型 npm 包,可以通過 dll 將其提前打包好,這樣在業務開發過程中就不用再重複去打包了,可以大幅縮減打包時間。

5. 升級到 webpack5

webpack5 利用 `持久緩存` 來提高構建性能,或許升級 webpack 後,前述的各種優化,都將成為歷史。

三、後向治理包含哪些內容?

後向治理主要保證構建結果的質量

1. 可視化分析構建結果

基於 webpack 的應用治理 3

很常見的就是 webpack-bundle-analyzeer,提供打包結果的可視化展示,如上圖給予的決策幫助是:

  • 是否需要按需加載;
  • 是否需要提取公共代碼;
  • 是否需要製定 cacheGroup 的策略。

2. 清理 deadcode

業務開發過程中,隨著業務迭代,經常有些文件、模塊及代碼被廢棄,這些廢棄代碼隨著時間推移,將逐漸變為歷史包袱,所以針對構建後結果,我們要做的就是清理其中的deadcode 。

前面 webpack-bundle-analyzeer 雖然是最常用的插件,但依舊有一些缺陷:

1)體積超小的 deadcode 模塊引用,無法被準確識別。

基於 webpack 的應用治理 4

例如上圖:

lodash 體積大一下子就能被發現,就會意識到重複引用或者是未使用

但 deadcode 模塊 c 體積很小,即便被 chunk1、chunk2 都引用了,也不一定能立刻發現,很容易被帶到線上

而且這種 deadcode 也無法通過 splitchunk 來進行優化,因為 splitchunk 根據引用次數提取公共代碼,無法分辨是否是廢棄代碼,所以對模塊 c.js 這種的 deadcode 就無力了

2)tree-sharking 只保留有用的代碼,但 deadcode 還在那裡。

tree-sharking 大家都了解,搖掉不需要的代碼,做為最終的輸出結果,但反過來說,這些廢棄代碼依舊在本地真實不虛的存在著。

所以如何能準確的清理掉 deadcode 呢?這就需要通過 webpack 的 统计信息(stats) 來進行更細節的分析

3. 統計信息(stats)

stats 是通過 webpack 編譯源文件時,生成的包含有關於模塊的統計數據的 JSON 文件,這些統計數據不僅可以幫助開發者來分析應用的依賴圖表,還可以優化編譯的速度。

webpack --profile --json > compilation-stats.json

通過上述全局命令即可輸出統計信息,例如:

{
  "version": "1.4.13", // Version of webpack used for the compilation
  "hash": "11593e3b3ac85436984a", // Compilation specific hash
  "time": 2469, // Compilation time in milliseconds
  "filteredModules": 0, // A count of excluded modules when `exclude` is passed to the `toJson` method
  "assetsByChunkName": {
    // Chunk name to emitted asset(s) mapping
    "main": "web.js?h=11593e3b3ac85436984a",
    "named-chunk": "named-chunk.web.js",
    "other-chunk": [
      "other-chunk.js",
      "other-chunk.css"
    ]
  },
  "assets": [
    // A list of asset objects
  ],
  "chunks": [
    // A list of chunk objects
  ],
  "modules": [
    // A list of module objects
  ],
  "errors": [
    // A list of error strings
  ],
  "warnings": [
    // A list of warning strings
  ]
}

其中:modules:表示 module 的集合

  • module:webpack 依賴樹中的真實模塊;
  • chunks:表示 chunk 的集合;
  • chunk:包含 entry 入口、異步加載模塊、代碼分割(code spliting)後的代碼塊。

通過對 modules 和 chunks 加以分析,就可以得到 webpack 完整的依賴關係,從而梳理出廢棄文件及廢棄代碼,同時也可以根據業務形態進行定制。

4. webpack-deadcode-plugin

前面提到分析 stats.json,但因為是原始數據,數據量比較大,有一定處理和清洗成本,所以可以使用開源的 webpack-deadcode-plugin 這個插件

基於 webpack 的應用治理 5

通過 webpack-deadcode-plugin,可以快速篩選出:

1)未使用的文件;

2)未使用的已暴露變量。

5. 結合 eslint、tslint 進行治理

lint 可以快速的掃描出未使用的變量,這能夠極大的提升我們的 deadcode 清理效率。

1)首先通過 lint 對未使用變量進行清理;

2)再通過 webpack-deadcode-plugin 再掃描出未使用文件和未使用的導出變量。

頓時整個應用乾乾淨淨,舒舒服服!

四、參考

speed-measure-webpack-plugin:

https://github.com/stephencookdev/speed-measure-webpack-plugin

happyPack:

https://github.com/amireh/happypack

webpack-bundle-analyzeer:

https://github.com/webpack-contrib/webpack-bundle-analyzer

stats:

https://webpack.js.org/api/stats/

webpack-deadcode-plugin:

https://github.com/MQuy/webpack-deadcode-plugin

作者介紹

阿里影業高級開發工程師 百命

相關閱讀

電影垂直行業的雲智開放平台如何煉成?

阿里工程師帶你了解 B 端垂類營銷中心如何設計?

雲智前端技術如何賦能場館院線?

60 秒售出 5 萬張票!電影節搶票技術揭秘

電影行業提升 DCP 傳輸效率,還能這樣做!

超大型場館的繪座選座解決方案

大型賽事穩定性保障:Dpath 為世界軍人運動會護航

世界頂級賽事的票務支撐:百萬座位與限時匹配

前端技術:Webpack 工程化最佳實踐

電影票房數據查詢服務高性能與高可用實踐