背景
随着項目的推移, 第三庫使用數量增加,業務代碼更是成倍增加,不知不覺發現webpack建構速度卻越來越慢,從當初的30s,變成5分鐘以上。 與此同時,一個同學的項目也遇到了打包慢的問題。 于是下定決心,花兩周潛心研究下如何提升webpack建構性能。
初步成果
兩周後,收獲滿滿的。初步戰果如下:
(1) 自己的項目: vue2(全家桶)+element-ui+axios+echarts+lodash+… 約120個頁面
dev:從90s+ 優化到 41s
product: 從9分鐘+ 優化到 43s
(2) 同學的項目: react + redux + antd + moment+ rc-table + … 約40個頁面
dev: 從2分鐘+ 優化到 12s
product: 從9分鐘+優化到 13s
總結優化方法
首先,優化思路是從webpack建構過程去分析,主要是解析和壓縮優化。
分析工具
(1) webpack-bundle-analyzer
可視化檢視打包後的檔案,以及檔案包含的内容。
主要注意兩點:
- 每個打包後檔案的大小,其實業務代碼chunk包一般在20k以内。如果大了,就可能是把第三方庫打包進去了。
-
打包後的檔案是否有重複引用的庫,應該提出來。
舉個栗子:
優化前
從圖中我們發現,打包後的檔案中, 很多包含了node_modulles/echarts, zrender兩個庫。 此時,我們就可以用DllPlugin插件,把這兩個第三方庫提出來, 減少單個業務代碼頁面打包後的檔案大小, 避免重複編譯。
優化後
提取第三方庫後,我們發現頁面小了很多。 這時候又發現很多個檔案都包含了公共代碼src/utils/_serivce.js , 這種公共的業務代碼也是常見的問題, 通常有以下幾種辦法
- 按需加載 import { a } from xxx, 每個頁面隻引用需要的。需要配合export使用,修改源檔案導出方式。
- 公用方法挂載到根執行個體, 如vue中, Vue.prototype._utils = _utils 。 也需要修改源檔案,且不宜過大。
- Tree Shaking 打包後,抖落掉不需要的代碼, 不用修改源碼。
(2)webpack - -profile
可以檢視打包過程中,每個步驟的速度。如果某個步驟卡了很長時間,就把對應關鍵字放到github上搜尋, 可以發現一些很好的解決方法。
其中,同學的那個項目,打包過程中卡住在91% additional asset processing, 而且卡住了幾分鐘。 後來在github的webpack項目的issue中找到解決辦法, 更新webpack版本至2.7, 以及把extract-text-webpack-plugin庫更新至2.1.2。 居然一下快了幾分鐘~
另外, 把優化方法分成通用,開發,生産三類。
優先級從高到低,如下:
通用優化
-
使用 DllPlugin
原理是把第三方庫檔案分離出來單獨編譯,并且緩存; 極大的減少業務頁面的編譯時間, 以及編譯後的檔案大小。
優化時間: 3分鐘+
詳細:
https://webpack.js.org/plugins/dll-plugin/ (官網)
https://www.cnblogs.com/ghost-xyx/p/6472578.html
-
更新webpack和node
(1)webpack最新版本為v4+, 官方稱對比v3, 性能提升了60%。這次優化時,還是用v2.7, 因為更新v4失敗了。
優化時間: 待實踐。
詳細: https://blog.csdn.net/qq_26733915/article/details/79446460
(2)更新node, node目前穩定版本為v8.9.4。保持最新版本能夠保證編譯性能,npm保持最新也能建立更高效的子產品樹以及提高解析速度。
優化時間: 30s+
詳細: https://www.cnblogs.com/xinjie-just/p/7061619.html
-
多線程解析
(1) happypack, 多線程解析檔案,如babel-loader等耗時較長的。
還可以配合cache-loader使用。
優化時間: 15s左右
詳細: https://github.com/amireh/happypack
要求: webpack 2+
(2) thread-loader: 還沒實踐過,原理也是多線程解析。
優化時間: 待實踐
詳細: https://webpack.js.org/loaders/thread-loader/
-
緩存
cache-loader
優化時間: 約5s
詳細: https://webpack.js.org/loaders/cache-loader/
-
提取公共代碼
CommonsChunkPlugin
這次實踐中使用了CommonsChunkPlugin,并沒有什麼明顯效果, 然後就換成了DllPlugin。
也許,這兩個項目都是單頁應用,多頁應用可能效果比較好。還是個疑惑的地方~
優化時間: 待實踐
詳細: https://webpack.js.org/plugins/commons-chunk-plugin/
-
其它
(1) loaders應盡可能配置解析路徑include參數,排除路徑exclude參數, 減少解析時查詢範圍。
(2) Tree Shaking. 按需加載思想差不多,去掉多餘的代碼。
優化時間: 待實踐。
詳細: https://webpack.js.org/guides/tree-shaking/
(3) 第三庫的選擇, 盡量少用,或用精簡的庫替代;一些工具函數,最好用原生替代。
開發環境優化
- 在記憶體中編譯 webpack-dev-middleware等
-
devtool 設定成cheap-module-eval-source-map, 已經能滿足調試需求, 編譯能更快。
優化時間: 10s 左右
生産環境優化
-
多線程壓縮
庫: webpack-parallel-uglify-plugin
顧名思義, 多線程壓縮,配合緩存大大減少了壓縮時間,替代了自帶的UglifyJsPlugin
優化時間: 40s+
詳細:
// 多線程壓縮插件
const ParallelUglifyPlugin = require('webpack-parallel-uglify-plugin');
plugins: [
new ParallelUglifyPlugin({
cacheDir: '.cache/',
uglifyJS:{
output: {
comments: false
},
compress: {
dead_code: true,
warnings: false,
drop_debugger: true,
drop_console: true
}
},
sourceMap: false
})
]
2.多線程編譯
庫: parallel-webpack
優化時間: 待實踐
詳細: https://github.com/trivago/parallel-webpack
3.去掉source-map
大多數情況,生産環境不需要詳細源碼。
優化時間: 10s+
分享優化過程
解決問題的思路有時候更重要
- 很多技術官網是解決問題最快的方式, 如webpack建構優化官網文章
- 針對大部分第三方庫的疑難雜症,在github上對應該庫的issue,是最快解決問題的地方
- 一時沒有找到解決辦法, 休息一下,下次也許就會有不一樣的了解。
立個flag
- 盡快完成待實踐的技術部分,出下一篇優化文章。
- 研究優化首頁加載。