React之craco打包优化配置
随着项目规模的增加,当文件越来越多、引入的第三方组件库越来越多的时候,如果使用脚手架默认配置的话,打包出来的项目体积会变得越来越大,为了解决这个问题,需要我们去自定义 webpack 配置。
这里有两种方法,第一种是执行 npm run eject 暴露出 webpack 的配置项,然后更改里面的配置文件(不推荐)。第二种方法是使用第三方库 @craco/craco,这里使用的是第二种
需求是开启 gzip 压缩,关闭 sourcemap 文件生成,js 分模块打包,开启 tree-shaking,路径别名配置,cdn 外部资源不打包等
1、安装相关依赖
npm install @craco/craco
// 由于这些插件只是在打包的时候需要,生产环境下不需要,因此我们安装到开发环境下
npm install uglifyjs-webpack-plugin@2 compression-webpack-plugin@6 css-minimizer-webpack-plugin@1 terser-webpack-plugin@4 -D --force
1
2
3
4
2
3
4
2、在项目根目录下创建 craco.config.js 配置文件
// craco.config.js
const path=require( 'path' );
// Webpack 4及以下版本使用该插件
// 用于js代码压缩和混淆的插件,减小js代码体积,提高加载速度,保护代码不被轻易篡改
// const UglifyJsPlugin=require( "uglifyjs-webpack-plugin" );
// 安装版本5或6,高版本会报错
const CompressionWebpackPlugin=require( 'compression-webpack-plugin' );
// 安装1版本的,高版本会报错
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
// 如果使用 webpack v4,则必须安装 terser-webpack-plugin v4 的版本,否则配置sourceMap时会报错
// Webpack 5及以上版本使用这个
// 用于js代码压缩和混淆的插件,减小js代码体积,提高加载速度,保护代码不被轻易篡改
const TerserPlugin = require("terser-webpack-plugin");
// 用于打包性能分析
// const { BundleAnalyzerPlugin }=require( "webpack-bundle-analyzer" )
module.exports = {
webpack: {
alias: {
'@': path.resolve(__dirname, 'src'),
},
plugins: [
// 打包性能分析
// new BundleAnalyzerPlugin({
// openAnalyzer: false, // 是否在默认浏览器中自动打开报告
// analyzerMode: 'static', // 生成分析报告report.html
// })
// 建议安装5或6版本,过高会报错
new CompressionWebpackPlugin( {
algorithm: 'gzip',
test: /\.js$|\.html$|\.json$|\.css/,
threshold: 10240, // 只有大小超过10k的资源会被处理
minRatio: 0.8, // 最小压缩比达到0.8时才会被压缩
deleteOriginalAssets: false, // 是否删除原文件,默认为false
} ),
/*
Webpack 5及以上版本
用于js代码压缩和混淆的插件,减小js代码体积,提高加载速度,保护代码不被轻易篡改
*/
new TerserPlugin( {
parallel: true,
sourceMap: false,
terserOptions: {
compress: {
drop_console: true,
drop_debugger: true
},
},
} ),
// 压缩css代码
new CssMinimizerPlugin(
{
parallel: true, // 使用多进程并行执行任务来提高构建效率
sourceMap: false, // 不生成map文件
}
),
// Webpack 4及以下版本
// new UglifyJsPlugin({
// uglifyOptions: {
// compress: {
// drop_debugger: true,
// drop_console: true, //生产环境自动删除console
// },
// warnings: false,
// },
// sourceMap: false,
// parallel: true, //使用多进程并行运行来提高构建速度。默认并发运行数:os.cpus().length - 1。
// } ),
],
optimization: {
splitChunks: {
chunks: 'all',
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10,
name (module) {
// node_modules/packageName
const packageName = module.context.match(
/[\\/]node_modules[\\/](.*?)([\\/]|$)/
)[1]
return `npm.${packageName.replace("@", "")}`
},
},
}
},
runtimeChunk: true, // 避免文件的频繁变更导致浏览器缓存失效
usedExports: true, // 开启tree-shaking
minimize: true,
},
// 不生成map文件
devtool: false,
// 配置cdn外部资源不打包
externals: {
'react': 'React',
'react-dom': 'ReactDOM',
}
},
};
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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
上述配置也可更改如下:
const path=require( 'path' );
// Webpack 4及以下版本使用该插件
// 用于js代码压缩和混淆的插件,减小js代码体积,提高加载速度,保护代码不被轻易篡改
// const UglifyJsPlugin=require( "uglifyjs-webpack-plugin" );
// 如果webpack版本不够高,则建议安装版本5或6,否则高版本会报错
const CompressionWebpackPlugin=require( 'compression-webpack-plugin' );
// 如果webpack版本不够高,则建议安装1版本的,否则高版本会报错
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin");
// 如果使用 webpack v4,则必须安装 terser-webpack-plugin v4 的版本,否则配置sourceMap时会报错
// Webpack 5及以上版本使用这个
// 用于js代码压缩和混淆的插件,减小js代码体积,提高加载速度,保护代码不被轻易篡改
const TerserPlugin=require( "terser-webpack-plugin" );
module.exports = {
webpack: {
alias: {
'@': path.resolve(__dirname, 'src'),
},
configure: ( webpackConfig, { env, paths } ) => {
const isEnvProduction = env === 'production';
webpackConfig.devtool = false; // 不生成map文件
if ( isEnvProduction ) {
// 用于js代码压缩和混淆的插件,减小js代码体积,提高加载速度,保护代码不被轻易篡改
webpackConfig.plugins.push(
new CompressionWebpackPlugin( {
algorithm: 'gzip',
test: /\.js$|\.html$|\.json$|\.css/,
threshold: 10240, // 只有大小超过10k的资源会被处理
minRatio: 0.8, // 最小压缩比达到0.8时才会被压缩
deleteOriginalAssets: false, // 是否删除原文件,默认为false
} )
)
webpackConfig.plugins.push(
new TerserPlugin({
parallel: true,
terserOptions: {
compress: {
drop_console: true,
drop_debugger: true,
},
},
})
)
webpackConfig.plugins.push(
new CssMinimizerPlugin(
{
parallel: true, // 使用多进程并行执行任务来提高构建效率
}
)
)
webpackConfig.optimization = {
splitChunks: {
chunks: 'all',
maxInitialRequests: Infinity,
minSize: 20000,
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name ( module, chunks, cacheGroupKey ) {
const moduleFileName = module
.identifier()
.split('/').reduceRight((item) => item);
const allChunksNames = chunks
.map( ( chunk ) => chunk.name )
.join( ',' );
return `${cacheGroupKey}-${allChunksNames}-${moduleFileName}`
}
}
},
},
runtimeChunk: true,
usedExports: true,
minimize: true,
}
// 配置cdn外部资源不打包
webpackConfig.externals = {
'react': 'React',
'react-dom': 'ReactDOM',
'echarts': 'echarts'
}
}
return webpackConfig
},
}
};
// 如果想cdn外部资源不打包还需要在index.html文件中引入相应的三方包
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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
此时,配置已完成,可以愉快的玩耍了
编辑 (opens new window)
上次更新: 7/1/2024, 4:56:33 PM