【智能优化】自动分包策略,Webpack性能提升新维度(6)
不同与手动分包,自动分包是从实际的角度出发,从一个更加宏观的角度来控制分包,而一般不对具体哪个包要分出去进行控制
因此使用自动分包,不仅非常方便,而且更加贴合实际的开发需要
要控制自动分包,关键是要配置一个合理的分包策略
有了分包策略之后,不需要额外安装任何插件,webpack会自动的按照策略进行分包
实际上,webpack在内部是使用
SplitChunksPlugin
进行分包的
过去有一个库CommonsChunkPlugin
也可以实现分包,不过由于该库某些地方并不完善,到了webpack4
之后,已被SplitChunksPlugin
取代
从分包流程中至少可以看出以下几点:
- 分包策略至关重要,它决定了如何分包
- 分包时,webpack开启了一个新的chunk,对分离的模块进行打包
- 打包结果中,公共的部分被提取出来形成了一个单独的文件,它是新chunk的产物
1. 基本配置
首先,我们需要在 webpack.config.js
中配置 optimization.splitChunks
来设置分包策略。
修改 webpack.config.js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const CleanWebpackPlugin = require('clean-webpack-plugin').CleanWebpackPlugin;
module.exports = {
mode: 'development',
entry: {
index: './src/index.js',
other: './src/other.js'
},
output: {
filename: '[name].[contenthash].js',
path: path.resolve(__dirname, 'dist')
},
devtool: 'source-map',
module: {
rules: [
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader']
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: './public/index.html',
chunks: ['index'] // 自动处理被分离出去的chunk
}),
new HtmlWebpackPlugin({
template: './public/other.html',
chunks: ['other'] // 自动处理被分离出去的chunk
}),
new MiniCssExtractPlugin({
filename: '[name].[contenthash].css',
chunkFilename: '[id].[contenthash].css'
}),
new CleanWebpackPlugin({
cleanOnceBeforeBuildPatterns: ['**/*', '!dll', '!dll/**/*'] // 排除dll目录及其内容
})
],
optimization: {
splitChunks: {
chunks: 'all', // 对所有类型的chunk应用分包策略
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/, // 匹配node_modules中的模块
priority: -10 // 优先级
},
default: {
minChunks: 2, // 至少被两个chunk引用才会进行分包
priority: -20,
reuseExistingChunk: true // 重用已经被分离出去的chunk
},
styles: {
name: 'styles',
type: 'css/mini-extract',
chunks: 'all',
enforce: true
}
}
}
}
};
2. 解释配置
- entry: 定义了两个入口文件
index.js
和other.js
。 - output: 输出文件名包含
[contenthash]
以确保缓存失效。 - module.rules: 处理 CSS 文件,使用
MiniCssExtractPlugin
提取样式到单独的 CSS 文件中。 - plugins:
HtmlWebpackPlugin
: 自动生成 HTML 文件并注入打包后的 JavaScript 文件。MiniCssExtractPlugin
: 提取 CSS 到单独的文件。CleanWebpackPlugin
: 清理输出目录,但保留dll
目录及其内容。
- optimization.splitChunks:
chunks: 'all'
: 对所有类型的 chunk 应用分包策略。cacheGroups
:vendors
: 匹配node_modules
中的模块,并赋予较低的优先级-10
。default
: 至少被两个 chunk 引用的模块会被分包,赋予更低的优先级-20
,并且重用已存在的 chunk。styles
: 将所有 CSS 模块提取到一个名为styles
的 chunk 中。
3. 示例项目结构
假设你的项目结构如下:
my-project/
├── dist/
├── node_modules/
├── public/
│ ├── index.html
│ └── other.html
├── src/
│ ├── index.js
│ ├── other.js
│ └── styles.css
├── package.json
└── webpack.config.js
public/index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Index Page</title>
</head>
<body>
<h1>Index Page</h1>
</body>
</html>
public/other.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Other Page</title>
</head>
<body>
<h1>Other Page</h1>
</body>
</html>
src/index.js
import _ from 'lodash';
import $ from 'jquery';
import './styles.css';
console.log(_.isArray([]));
console.log($('body'));
src/other.js
import _ from 'lodash';
import $ from 'jquery';
import './styles.css';
console.log(_.isEmpty({}));
console.log($('body'));
src/styles.css
body {
background-color: #f0f0f0;
}
4. 运行命令
运行以下命令来启动开发服务器或构建项目:
# 启动开发服务器
npx webpack serve
# 构建项目
npx webpack
总结
通过上述配置,Webpack 会根据设定的分包策略自动将公共模块(如 lodash
和 jquery
)和样式文件提取到单独的 chunk 中。这样做的好处包括:
- 提高加载性能:通过按需加载和缓存管理,减少了初始加载时间。
- 减少重复代码:公共模块只被打包一次,避免了重复代码。
- 更好的缓存利用:由于公共模块的 hash 不会频繁变化,浏览器可以更好地利用缓存。
通过这种方式,你可以更高效地管理和优化大型项目的代码分割和打包过程。