阅读数:

react项目 webpack 3.x打包效率提升记

0

说明

webpack是大家都知晓的主流打包工具,或者形象的讲是“模块打包机”,在之前的博客中也
总结了1.x–>2.x的核心步骤。今天要介绍的如何提升
前端项目的打包效率,缩短打包时间,进而缩短项目部署的时间。
大家都知道,随着项目原来越大,需要解析和处理的文件也越来越多,构建是文件读写和计算密集型的操作,
这时候webpack的处理效率会越来越慢。运行在nodejs的webpack是单线程模式,也就说它不能
同时处理好几件事,所以这也就说慢的原因。那么有没有办法让webpack并行处理呢。答案肯定是有的。

  • happypack
    首先介绍一下happypack
    它的思想就是将
    任务拆分成多个子进程进行并发处理,处理完成后将结果返回给主进程也就是webpack进程。那么怎么
    接入呢?
    先看看没接入前:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    module: {
    rules: [{
    test: /\.(js|jsx)$/,
    exclude: /node_modules/,
    loader: 'babel-loader'
    },
    , {
    test: /\.(css|less)$/,
    use: ExtractTextPlugin.extract({
    fallback: 'style-loader',
    use: [{
    loader: 'css-loader'
    }, {
    loader: 'less-loader'
    }]

    })
    }
    ...
    }

使用了babel-loader对es6的语法进行转化。接入happypack:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
const HappyPack = require('happypack');
const happyThreadPool = HappyPack.ThreadPool({ size: 4 }); // 默认3个进程
module: {
rules: [{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
loader: 'happypack/loader?id=happyBabel',
},
{
test: /\.(css|less)$/,
loader: 'happypack/loader?id=styles',
},
...
},
// add a new plugin
plugins: [
new HappyPack({
id: 'happyBabel', // 必须和rules里的id保持一致
loaders: [{
loader: 'babel-loader?cacheDirectory=true',
}],
threadPool: happyThreadPool,
verbose: true,
}),
new HappyPack({
id: 'styles',
threadPool: happyThreadPool,
loaders: [ 'style-loader', 'css-loader', 'less-loader' ]
})
...
]

注:对于样式的happpack可能会报错,如果报错,还原样式部分配置即可。

  • webpack-parallel-uglify-plugin

代码并行转换完了,但是最最费时间的是js的压缩,在常用的配置中我们会使用webpack插件
uglifyjs-webpack-plugin

1
2
3
4
5
6
7
8
9
10
11
12
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
plugins: [
new UglifyJSPlugin({
sourceMap: false,
uglifyOptions: {
ecma: 5,
ie8: true,
mangle: false
}
}),
....
]

这里也是单线程的,对于越来越多越大的js,压缩时间可想而知。同理,我们也可以参考
happypack的思想,让并发起来,这里介绍另个神器webpack-parallel-uglify-plugin
原理类似。具体接入方法如下:
讲原来部分注销掉

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
const ParallelUglifyPlugin = require('webpack-parallel-uglify-plugin');
plugins: [
/*new UglifyJSPlugin({
sourceMap: false,
uglifyOptions: {
ecma: 5,
ie8: true,
// 不能压缩变量名,会导致项目无法发起异步请求
mangle: false
}
}),*/
// 使用 ParallelUglifyPlugin 并行压缩输出JS代码
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
}
}
}),
...
]

至此,在两大神器的加盟下,实际效果到底如何呢?
实际项目,pack 5次求平均,测试结果如下

before only with ParallelUglifyPlugin with ParallelUglifyPlugin & happypack
4min30s 1min30s <1min

^-^欢迎回复交流^-^


0
赏点咖啡钱^.^