webpack 分包的好处
- 单个包太大影响首屏渲染速度(出现白屏)
- 可以按需加载文件
- 可以分割更小的包,加载更快
- 可以控制资源的加载优先级, 提供代码的加载性能
入口起点
- 使用 entry 配置手动分离代码, 配置多入口的方式。如:
module.exports = {
/**
* 可以将entry配置成一个对象就可以配置多个入口,webpack打包的时候会分别打包
* 注意: 还需要配置 filename,不然webpack不知道要打包那个文件
* 问题?: 如果多个入口文件都用了同一个包webpack在打包的时候都会打包到对应的js文件中,该怎么处理? (入口依赖)
* 回答: 通过配置单独的包,然后在配置入口的时候依赖这个包,从而解决多个入口依赖相同的包
*/
entry: {
// 相同依赖的库单独打包
common: ['axios'],
// 写成对象的形式,
index: {
// import 打包时从哪个文件开始
import: './src/index.js',
// 可以通过 dependOn 属性表示要依赖哪个包, 在打包时就会去找这个common的依赖
dependOn: 'common'
},
main: {
import: './src/main.js',
dependOn: 'common'
}
},
};
自定义分包
- 使用 SplitChunksPlugin 去重和分离代码。如:
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name]-bundle.js',
clean: true,
chunkFilename: '[name]-chunk.js'
},
devServer: {
open: true
},
// 优化配置
optimization: {
/**
* 生成chunkId的算法配置
* named: 根据完整的文件路径名生成名称
* deterministic: 在不同的环境中生成相同的值
* natural: 在webpack4中有,使用顺序的id值
*
* 推荐: 在生成环境中使用 deterministic, 在开发环境中使用 named
*/
chunkIds: 'deterministic',
/**
* 配置运行时所有chunk需要用到的代码打包待一个包中
*/
runtimeChunk: {
// 设置包的名称
name: 'runtime'
},
/**
* 自定义拆分模块分包,在 production 环境下默认开启
* 默认是对 node_module 目录下导入的包进行拆包
*/
splitChunks: {
/**
* chunks: 配置那些模块需要进行分包操作,默认值 async,
* 属性值:
* - async: 只有动态导入的模块会进行分包操作
* - all: 所有通过导入的模块都会进行分包, 打包到同一个包中
*
* 还可以写出函数形式,根据name判断那些包需要进行分包
*/
chunks: 'all',
// chunks: (chunk) => {
// return chunk.name == 'about';
// },
/**
* 当一个包大于指定的大小时,继续进行拆包(byte单位)
*/
// maxSize: 20000,
/**
* 将包拆分成小于minSize的包
*/
// minSize: 10000,
/**
* 自定义对需要拆包的内容进行拆分
*/
minSize: 100,
cacheGroups: {
vendors: {
// 通过匹配路径来进行拆包,在node_module下导入的代码都拆分成一个包
test: /[\\/]node_modules[\\/]/,
filename: '[id]_vendors.js'
},
utils: {
// 在utils下导入的代码都拆分成一个包
test: /utils/,
filename: '[id]_utils.js'
}
}
}
},
};
动态导入
- 通过 import 函数动态导入代码 webpack 会单独进行分包, 用不到的代码就不需要打包,在需要使用的时候在在加载下来。如:
import('xxx.js')
Prefetch(预获取) 和 Preload(预加载)
prefetch
- 作用: 在浏览器空闲时下载包
- 用法: 在使用 import 函数时通过添加魔法注释 /* webpackPrefetch: true */ 告诉 webpack 这个是需要预请求的。如:
import(
/* webpackPrefetch: true */
'xxx.js'
)
preload
- 作用: 可以让拆分的包跟随主包下载时并行下载
- 用法: 在使用 import 函数时通过添加魔法注释 /* webpackPreload: true */ 告诉 webpack 这个是需要预请求的。如:
import(
/* webpackPreload: true */
'xxx.js'
)
CDN 方式
webpack.config.js 中
module.exports = {
/**
* cdn引入第三方包:
* 1. 先排除需要的第三方包
* 2. 在index.html中引入你要的第三方包的cdn
*/
// 排除那些包不需要进行打包
externals: {
// key(属性值): 要排除的库的名称
// value(值): 是要使用第三方包的全局变量
react: 'React',
axios: 'axios'
},
};
index.html 中:
<!-- 通过引入cdn的方式使用第三方包 -->
<script src="https://cdn.bootcdn.net/ajax/libs/react/18.2.0/umd/react.production.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/axios/1.5.0/axios.min.js"></script>
CSS 样式抽离(MiniCssExtractPlugin)
- 作用: 将 CSS 抽离到单独的的文件当中
- 用法:
moduel.exports = {
plugins: [
// 1. 在plugins中使用 MiniCssExtractPlugin
new MiniCssExtractPlugin({
filename: '[name].css',
chunkFilename: '[name]_chunk.css'
})
],
module: {
// 2. 在匹配规则中使用MiniCssExtractPlugin的loader和css-loader处理 .css 后缀的文件
rules: [{ test: /\.css$/, use: [MiniCssExtractPlugin.loader, 'css-loader'] }]
}
}
占位符(placeholders)
[id]: 会根据配置的 chunksId 生成对应的算法
webpack.config.js
module.exports = {
output: {
// id的值就是根据chunkIds配置的属性值生成的值
filename: '[id]-bundle.js',
chunkFilename: '[id]-chunk.js'
},
/**
* 生成chunkId的算法配置
* named: 根据完整的文件路径名生成名称
* deterministic: 在不同的环境中生成相同的值
* natural: 在webpack4中有,使用顺序的id值
*
* 推荐: 在生成环境中使用 deterministic, 在开发环境中使用 named
*/
optimization: {
chunkIds:'deterministic',
}
}
[hash]:
- 作用: 根据 chunk 的内容生成值,每次内容改变都会重新生成新的值
- 比如: 有个 main.js 页面,你改变了 main.js 中的内容,那么打包后的 hash 值就会改变
webpack.config.js
module.exports = {
output: {
filename: '[hash]-bundle.js',
chunkFilename: '[hash]-chunk.js'
},
}
[chunkhash]:
- 作用: 根据 chunk 的内容生成值,每次内容改变都会重新生成新的值。
- 注意: 如果导入的模块也做了分包处理,那么导入模块的 chunk 的 hash 值也会改变
webpack.config.js
module.exports = {
output: {
filename: '[chunkhash]-bundle.js',
chunkFilename: '[chunkhash]-chunk.js'
},
}
[contenthash]:
- 作用: 根据 chunk 的内容生成值,每次内容改变都会重新生成新的值。
- 注意:
contenthash只会改变当前改变模块 chunk 的 hash 值,导入的模块做了分包处理的话 hash 值不会改变,可以解决chunkhash的问题
webpack.config.js
module.exports = {
output: {
filename: '[contenthash]-bundle.js',
chunkFilename: '[contenthash]-chunk.js'
},
}