希沃ENOW大前端javascript
公司官網:CVTE(廣州視源股份)css
團隊:CVTE旗下將來教育希沃軟件平臺中心enow團隊前端
本文做者:java
Hello,你們好,我是小羽同窗,一個平凡而又不甘於平凡的前端開發工程師。react
今天的話,主要是想和你們聊聊小羽
是怎麼把一個react老項目
的構建
時間減小70%+
的。webpack
小羽最近接手了一個3年前
的老項目web
看了下版本,react 16.0
+ ts
+ webpack4
,感受還行shell
可是據說中間有接近一年
的時間沒人維護,本來熟悉項目的人都溜了。npm
還沒來的及詳細研究代碼,需求就到了。babel
只能硬着頭皮
上了,還好有個人導師
和兵哥
從旁協助。
前期的開發也算是有驚無險
的渡過了吧。
最近幾天剛開發完一個版本,而後發現咱們項目的構建時間
實在過久了
。
XDM,若是我說打包
一個react項目竟然要150s
,大家敢相信嗎?
小羽
當時也是懵了
147s
,這但是2分半的時間。。。
看了一下cpu的利用率
,平均下來大概就是20%
左右。這個利用率也過低了吧?徹底沒有把cpu的性能發揮
出來。
而後小羽找了下webpack打包優化相關的包。而後發現了網上大多數都是說happypack
這個插件能夠進行多線程
的優化。
那就整起唄。
npm install happypack --save-dev
複製代碼
配置大概以下
const HappyPack = require('happypack');
const happyThreadPool = HappyPack.ThreadPool({size: require('os').cpus().length})
module.exports = {
...
module: {
rules: [
test: /\.js$/,
use: ['happypack/loader?id=js'],
],
plugins: [
...,
new HappyPack({
id: 'js',
loaders: ['babel-loader'],
threadPool: happyThreadPool,
})
]
}
}
複製代碼
運行了一下
嗯,還不錯,單js的轉譯就減小了20s
。
然而,小羽在css/less
打包優化的時候遇到了問題。
緣由是css/less
中用到了mini-css-extract-plugin
這個樣式抽離插件,刪除這個插件後打包又是正常的。
查閱npm中的文檔,發現做者因爲對改項目的興趣消退,在兩年前已經斷更了
。。。
而後做者給咱們推薦了thread-loader
,那就轉到thread-loader中去看看吧。
thread-loader
中提到,thread-loader中是沒法使用自定義加載器 API
(即經過插件)。
而loader的加載順序是從右往左
,從下往上
加載的。
像下面這個loader的加載順序則是less-loader
=> css-loader
=> style-loader
{
test: /\.less$/,
use: [
'style-loader',
'css-loader',
'less-loader'
],
},
複製代碼
那麼問題解決,只要咱們在引用mini-css-extract-plugin
前加載thread-loader
就不會報錯了。
完成全部的配置後,我們再來嘗試一下。
添加了thread-loader
的優化後打包構建的時間大概來到了120s
左右,和未優化前相比,減小了25-30s
。
而後cpu的利用率
也終於起來了,在loader編譯階段,利用率能夠提高到40%
多。
但是120s
的時間仍是很長,這時候怎麼處理呢?
其實在webpack的打包構建中耗時較多
的兩個步驟應該是loader的轉譯
以及代碼的混淆壓縮
。(前提是得有這兩個)
轉譯已經搞定了,那我們處理混淆壓縮吧。
看了下項目,發現用的是uglifyjs-webpack-plugin
這個插件進行混淆壓縮。
那就看下官網吧
嗯,你肯定沒有在逗我嗎?又是兩年前斷更了
,這。。。
我不想優化
了!!!
都是些啥玩意
啊!!!
哈哈哈,開個玩笑
。
優化那是必須得繼續的。那就只可以繼續查閱資料啦。
一個偶然的機會,發現了我們接下來的主角——terser-webpack-plugin
記住,若是是webpack4
的版本那麼也要安裝terser-webpack-plugin
v4的版本。v5的版本是給webpack5
來使用的。
小羽這邊接受的項目是webpack4
,那就用v4
的,而後看了下插件的版本。v4最新的
是4.2.3
npm install terser-webpack-plugin@4.2.3 --save-dev
複製代碼
const TerserPlugin = require('terser-webpack-plugin');
module.exports = {
...
optimization:{
minimizer: [
new TerserPlugin({
parallel: require('os').cpus().length - 1,
terserOptions:{
compress:{
inline:false
},
mangle: {
safari10: true
}
}
})
]
}
}
複製代碼
parallel
參數是用來設置你啓動的線程數
的。require('os').cpus().length - 1,表明獲取你電腦全部線程-1的數量。
而後這裏得提一下,
並非
啓動的線程數量越多就越好
的(包括前面的thread-loader)。由於咱們每啓動一個線程都是須要消耗必定的時間的,這個時間約爲
600ms
。舉個🌰,假如如今你用的是一臺8核16線程的電腦。我們把全部的線程都啓動起來,那麼啓動的時間約爲
9.6s
。可是當我們的項目比較小,本來打包的時間可能就
五、6s
,壓縮的時間可能連600ms
都不到,這樣的話我們的打包優化就變成了負優化
了。因此並非
每個項目
都須要開啓
多線程的。是否要開啓?開啓多少個線程?這些都是須要看狀況的。
terser-webpack-plugin
的terserOptions
參數基本與uglifyjs-webpack-plugin
中的uglifyOptions
是一致的,直接平滑升級,美滋滋~
那我們來測試一下吧~
構建時間約爲41s
,nice~
而後在看一下我們混淆壓縮時候的cpu負載
也是彪了上來,cpu負載最高可到92%
。
最後我們計算一下
未優化前147s
,優化後41s
,一共減小了106s
,減小了快兩分鐘
的時間。
那我們在計算一下提高的性能,(147-41)/147≈0.72。提高了72%
。
小羽在本文中和小夥伴們聊了下在工做中是如何優化
一個老項目的webpack打包構建經歷,向小夥伴們介紹了happypack
、thread-loader
以及terser-webpack-plugin
的用法。但願可以給小夥伴們在webpack
的構建中帶來一些幫助
,也但願小夥伴們能夠從中獲得一些啓發
~