如何让老项目的打包构建时间减小70%?

希沃ENOW大前端javascript

公司官网:CVTE(广州视源股份)css

团队:CVTE旗下将来教育希沃软件平台中心enow团队前端

本文做者:java

小羽名片.png

Hello,你们好,我是小羽同窗,一个平凡而又不甘于平凡的前端开发工程师。react

今天的话,主要是想和你们聊聊小羽是怎么把一个react老项目构建时间减小70%+的。webpack

小羽最近接手了一个3年前的老项目web

看了下版本,react 16.0 + ts + webpack4,感受还行shell

可是据说中间有接近一年的时间没人维护,本来熟悉项目的人都溜了。npm

image-20210621194704744-4276028.png

还没来的及详细研究代码,需求就到了。babel

只能硬着头皮上了,还好有个人导师兵哥从旁协助。

前期的开发也算是有惊无险的渡过了吧。

最近几天刚开发完一个版本,而后发现咱们项目的构建时间实在过久了

XDM,若是我说打包一个react项目竟然要150s,大家敢相信吗?

小羽当时也是懵了

147s,这但是2分半的时间。。。

image-20210621194742994-4276065.png

image-20210619103016762.png

image-20210619101825200.png

看了一下cpu的利用率,平均下来大概就是20%左右。这个利用率也过低了吧?彻底没有把cpu的性能发挥出来。

happypack

而后小羽找了下webpack打包优化相关的包。而后发现了网上大多数都是说happypack这个插件能够进行多线程的优化。

那就整起呗。

image-20210621194852686-4276134.png

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

thread-loader

然而,小羽在css/less打包优化的时候遇到了问题。

缘由是css/less中用到了mini-css-extract-plugin这个样式抽离插件,删除这个插件后打包又是正常的。

查阅npm中的文档,发现做者因为对改项目的兴趣消退,在两年前已经断更了。。。

而后做者给咱们推荐了thread-loader,那就转到thread-loader中去看看吧。

image-20210621164930138.png

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

image-20210621162853154.png

而后cpu的利用率也终于起来了,在loader编译阶段,利用率能够提高到40%多。

image-20210621162647423.png

terser-webpack-plugin

但是120s的时间仍是很长,这时候怎么处理呢?

其实在webpack的打包构建中耗时较多的两个步骤应该是loader的转译以及代码的混淆压缩。(前提是得有这两个)

转译已经搞定了,那我们处理混淆压缩吧。

看了下项目,发现用的是uglifyjs-webpack-plugin这个插件进行混淆压缩。

那就看下官网吧

嗯,你肯定没有在逗我吗?又是两年前断更了,这。。。

image-20210621164838233.png

我不想优化了!!!

都是些啥玩意啊!!!

image-20210621195043046.png

哈哈哈,开个玩笑

优化那是必须得继续的。那就只可以继续查阅资料啦。

一个偶然的机会,发现了我们接下来的主角——terser-webpack-plugin

记住,若是是webpack4的版本那么也要安装terser-webpack-plugin v4的版本。v5的版本是给webpack5来使用的。

image-20210621170220107.png

小羽这边接受的项目是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-pluginterserOptions参数基本与uglifyjs-webpack-plugin的uglifyOptions是一致的,直接平滑升级,美滋滋~

那我们来测试一下吧~

构建时间约为41s,nice~

image-20210621174356550.png

而后在看一下我们混淆压缩时候的cpu负载也是彪了上来,cpu负载最高可到92%

image-20210621173705668.png

最后我们计算一下

未优化前147s,优化后41s,一共减小了106s,减小了快两分钟的时间。

那我们在计算一下提高的性能,(147-41)/147≈0.72。提高了72%

image-20210621195143493.png

小结

小羽在本文中和小伙伴们聊了下在工做中是如何优化一个老项目的webpack打包构建经历,向小伙伴们介绍了happypackthread-loader以及terser-webpack-plugin的用法。但愿可以给小伙伴们在webpack的构建中带来一些帮助,也但愿小伙伴们能够从中获得一些启发~

相关文章
相关标签/搜索