希沃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
的构建中带来一些帮助
,也但愿小伙伴们能够从中获得一些启发
~