在使用 Webpack 进行前端代码打包的过程中,使用 CommonsChunkPlugin 可以将一些公共的代码提取出来,减小打包后的文件体积,提高页面加载速度。然而,在使用 CommonsChunkPlugin 时,也可能会遇到一些问题。本文将详细介绍这些问题,并提供解决方案。
问题描述
在使用 CommonsChunkPlugin 提取公共代码时,可能会出现以下问题:
- 提取的公共代码不完整,存在遗漏。
- 提取的公共代码过多,导致打包后文件体积反而更大。
这些问题的原因一般有两个:
- Webpack 的代码分割机制导致某些模块没有被正确分离出来。
CommonsChunkPlugin的配置不正确。
解决方案
问题一:提取的公共代码不完整
1.1 检查代码分割机制
Webpack 的代码分割机制有两种方式:同步和异步。同步代码分割在构建时就会执行,而异步代码分割则是在运行时进行。
在使用 CommonsChunkPlugin 提取公共代码时,如果某些模块没有被正确分离出来,可能是因为这些模块在异步代码中,而 CommonsChunkPlugin 只能处理同步代码。因此,我们需要使用 SplitChunksPlugin 来处理异步代码。
// www.javascriptcn.com code example
// webpack.config.js
module.exports = {
optimization: {
splitChunks: {
chunks: 'async',
minSize: 30000,
maxSize: 0,
minChunks: 1,
maxAsyncRequests: 5,
maxInitialRequests: 3,
automaticNameDelimiter: '~',
name: true,
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
}
}
}
}
};以上配置会将异步代码中的公共模块提取出来,使其被正确地处理。
1.2 检查 CommonsChunkPlugin 配置
如果代码分割机制没有问题,我们需要检查 CommonsChunkPlugin 的配置是否正确。
// www.javascriptcn.com code example
// webpack.config.js
module.exports = {
optimization: {
splitChunks: {
cacheGroups: {
commons: {
name: 'commons',
chunks: 'initial',
minChunks: 2
}
}
}
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: function(module) {
// any required modules inside node_modules are extracted to vendor
return (
module.resource &&
/\.js$/.test(module.resource) &&
module.resource.indexOf(path.join(__dirname, '../node_modules')) === 0
);
}
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
minChunks: Infinity
})
]
};以上配置会将所有入口文件中的公共模块提取出来,生成一个名为 commons 的文件。同时,还会将 node_modules 中的代码提取出来,生成一个名为 vendor 的文件。manifest 是用来处理 webpack 运行时代码的。
如果仍然存在公共代码不完整的问题,可以将 CommonsChunkPlugin 的 minChunks 参数设置为一个更小的值,例如 1,以保证所有公共模块都被正确提取。
问题二:提取的公共代码过多
2.1 检查代码分割机制
在使用 CommonsChunkPlugin 提取公共代码时,如果提取的公共代码过多,可能是因为我们没有正确地配置代码分割机制。我们可以使用 SplitChunksPlugin 来优化代码分割。
// www.javascriptcn.com code example
// webpack.config.js
module.exports = {
optimization: {
splitChunks: {
chunks: 'all',
minSize: 30000,
maxSize: 0,
minChunks: 1,
maxAsyncRequests: 5,
maxInitialRequests: 3,
automaticNameDelimiter: '~',
name: true,
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true
}
}
}
}
};以上配置会将所有代码中的公共模块提取出来,生成一个名为 commons 的文件。同时,还会将 node_modules 中的代码提取出来,生成一个名为 vendor 的文件。
2.2 检查 CommonsChunkPlugin 配置
如果代码分割机制没有问题,我们需要检查 CommonsChunkPlugin 的配置是否正确。在使用 CommonsChunkPlugin 时,我们需要注意以下几点:
CommonsChunkPlugin的name参数应该与SplitChunksPlugin的name参数相同,以确保公共模块被正确提取。CommonsChunkPlugin的minChunks参数应该设置为一个较大的值,以避免过多的公共模块被提取出来。
// www.javascriptcn.com code example
// webpack.config.js
module.exports = {
optimization: {
splitChunks: {
cacheGroups: {
commons: {
name: 'commons',
chunks: 'initial',
minChunks: 2
}
}
}
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: function(module) {
// any required modules inside node_modules are extracted to vendor
return (
module.resource &&
/\.js$/.test(module.resource) &&
module.resource.indexOf(path.join(__dirname, '../node_modules')) === 0
);
}
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
minChunks: Infinity
})
]
};以上配置会将所有入口文件中的公共模块提取出来,生成一个名为 commons 的文件。同时,还会将 node_modules 中的代码提取出来,生成一个名为 vendor 的文件。manifest 是用来处理 webpack 运行时代码的。
如果仍然存在公共代码过多的问题,可以将 CommonsChunkPlugin 的 minChunks 参数设置为一个更大的值,例如 3,以避免过多的公共模块被提取。
示例代码
以下是一个使用 CommonsChunkPlugin 提取公共代码的示例代码:
// www.javascriptcn.com code example
// webpack.config.js
const webpack = require('webpack');
const path = require('path');
module.exports = {
entry: {
app: './src/index.js',
vendor: [
'react',
'react-dom'
]
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].[chunkhash].js'
},
optimization: {
splitChunks: {
cacheGroups: {
commons: {
name: 'commons',
chunks: 'initial',
minChunks: 2
}
}
}
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: function(module) {
// any required modules inside node_modules are extracted to vendor
return (
module.resource &&
/\.js$/.test(module.resource) &&
module.resource.indexOf(path.join(__dirname, '../node_modules')) === 0
);
}
}),
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
minChunks: Infinity
})
]
};以上配置会将所有入口文件中的公共模块提取出来,生成一个名为 commons 的文件。同时,还会将 react 和 react-dom 提取出来,生成一个名为 vendor 的文件。manifest 是用来处理 webpack 运行时代码的。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/67d4a4d2a941bf71348bf96d