當前市面上大部分前端應用都是基於 webpack 進行構建,而隨着應用日益龐大,webpack 應用就會出現構建速度慢,構建結果體積大等一系列問題。
一、webpack 應用治理應該從哪個方向入手?
隨着應用的不斷迭代,webpack 應用最常見的兩個問題就是:
- 構建速度慢;
- 構建體積大。
有一個很簡單的劃分方式,就是以構建(build)爲分界線,分成前向治理和後向治理:
- 前向治理:提升構建速度;
- 後向治理:保證構建結果質量。
我們的治理方向,就是圍繞前向治理和後向治理。
二、前向治理包含哪些內容?
前向治理的核心概念,就是一個字 `快`,目的就是提升構建速度,市面上大部分 webpack 優化文章都是這一類提升構建速度的文章,所以這裏就簡單介紹一些不錯的實踐
1. 利用 SMP 採集 webpack 數據指標
數據先行,通過 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-bundle-analyzeer,提供打包結果的可視化展示,如上圖給予的決策幫助是:
- 是否需要按需加載;
- 是否需要提取公共代碼;
- 是否需要制定 cacheGroup 的策略。
2. 清理 deadcode
業務開發過程中,隨着業務迭代,經常有些文件、模塊及代碼被廢棄,這些廢棄代碼隨着時間推移,將逐漸變爲歷史包袱,所以針對構建後結果,我們要做的就是清理其中的 deadcode。
前面 webpack-bundle-analyzeer 雖然是最常用的插件,但依舊有一些缺陷:
1)體積超小的 deadcode 模塊引用,無法被準確識別。
例如上圖:
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-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
作者介紹:
阿里影業高級開發工程師 百命
相關閱讀