最近项目需求不是很紧张,本想着活动一下筋骨,放松放松,然而公司项目组很合时宜的召集前端开了一个小会,议题就是谈一谈目前项目中存在哪些问题,并针对存在的问题有没有方案进行改进、优化...
在这其中就谈到了webpack打包慢的问题,目前项目中用到的webpack是4.8.1版本,相比之前的版本可以说性能已经提高很多了,但是还存在一些不令人很满意的地方,比如说第一次打包的时候竟然耗时72394ms,将近一分多钟,连续重复几次,耗时只会多不会少(每次需要把node_modules删掉以保证准确性),如是看看有没有什么方式能提高打包速度,别说还真发现了一些可优化的地方
目前项目中使用的打包压缩工具是webpack默认的UglifyJS插件,它使用的是单线程压缩代码,也就是说当多个js文件需要被压缩时,它需要将文件一个一个进行压缩。因此在正式环境中打包压缩代码就显得非常慢(因为压缩JS代码需要先把代码解析成用Object抽象表示的AST语法树,再去应用各种规则分析和处理AST,导致这个过程耗时非常大)
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
new UglifyJsPlugin({
cache: true,
parallel: true,
sourceMap: false
})
复制代码
那有没有一种多线程或者是多进程的打包工具呢,别说还真有,这就是:webpack-parallel-uglify-plugin,当webpack有多个JS文件需要压缩和输出时,原来使用UglifyJS去一个个压缩并输出,相比UglifyJS,ParallelUglifyPlugin插件则会开启多个子进程,将多个文件压缩的工作分配给多个子进程去完成,但每个子进程还是通过UglifyJS去压缩代码,无非就是变成了并行处理的多个子任务,效率显然会提高很多。
首先 安装 webpack-parallel-uglify-plugin 插件:
npm i -D webpack-parallel-uglify-plugin
复制代码
配置如下:
const ParallelUglifyPlugin = require('webpack-parallel-uglify-plugin');
module.exports = {
plugins: [
new ParallelUglifyPlugin({
uglifyJS: {
output: {
/*
是否输出可读性较强的代码,即会保留空格和制表符,默认为输出,为了达到更好的压缩效果,
可以设置为false
*/
beautify: false,
/*
是否保留代码中的注释,默认为保留,为了达到更好的压缩效果,可以设置为false
*/
comments: false
},
compress: {
/*
是否在UglifyJS删除没有用到的代码时输出警告信息,默认为输出,可以设置为false关闭这些作用
不大的警告
*/
warnings: false,
/*
是否删除代码中所有的console语句,默认为不删除,开启后,会删除所有的console语句
*/
drop_console: true,
/*
是否内嵌虽然已经定义了,但是只用到一次的变量,比如将 var x = 1; y = x, 转换成 y = 5, 默认为不
转换,为了达到更好的压缩效果,可以设置为false
*/
collapse_vars: true,
/*
是否提取出现了多次但是没有定义成变量去引用的静态值,比如将 x = 'xxx'; y = 'xxx' 转换成
var a = 'xxxx'; x = a; y = a; 默认为不转换,为了达到更好的压缩效果,可以设置为false
*/
reduce_vars: true
}
}
}),
]
}
复制代码
test: 使用正则去匹配哪些文件需要被 ParallelUglifyPlugin 压缩,默认是 /.js$/.
include: 使用正则去包含被 ParallelUglifyPlugin 压缩的文件,默认为 [].
exclude: 使用正则去不包含被 ParallelUglifyPlugin 压缩的文件,默认为 [].
cacheDir: 缓存压缩后的结果,下次遇到一样的输入时直接从缓存中获取压缩后的结果并返回,cacheDir 用于配置缓存存放的目录路径。默认不会缓存,想开启缓存请设置一个目录路径。
workerCount:开启几个子进程去并发的执行压缩。默认是当前运行电脑的 CPU 核数减去1
sourceMap:是否为压缩后的代码生成对应的Source Map, 默认不生成,开启后耗时会大大增加,一般不会将压缩后的代码的 sourceMap发送给网站用户的浏览器。
uglifyJS:用于压缩 ES5 代码时的配置,Object 类型,直接透传给 UglifyJS 的参数。
uglifyES:用于压缩 ES6 代码时的配置,Object 类型,直接透传给 UglifyES 的参数。
最终的配置(根据实际情况取舍),项目中的打包速度提升了将近20s(54786ms),多次测试相差不大,可以说很可观了
new ParallelUglifyPlugin({
output:{
beautify: false,
comments: false
},
compress:{
warnings: false,
drop_console: true,
collapse_vars: true,
reduce_vars: true
},
test: /.js$/g,
include: [],
exclude: [],
cacheDir: '',
workerCount: '',
sourceMap: false
})
复制代码
webpack可以说是前端工程化不可或缺的一部分了,目前来看版本更新算比较快的,如何学习新的知识,面对新的问题,怕是避免不了的了,前端路漫漫,上下而求索,就这样吧