打包时会遇到的问题:
针对以上两个问题,利用splitChunks可以将各个模块进行分割,并提取出相同部分代码,从而缓解一个js过大、不能缓存第三方库的问题。
webpack 从 4.x 开始支持了零配置的特性,同时对块打包也做了优化,CommonsChunkPlugin已经被移除了,现在是使用optimization.splitChunks代替。(webpack5 splitChunks 配置和 webpack4 大体上一样)
在说SplitChunks前,先来了解几个概念,module、bundle、chunk都是什么?
module:模块,在webpack中任何文件都可以作为一个模块,借用官网的图片,左侧的这些类型文件,都可以认为是一个模块,只是需要配置不同的loader,将文件转换成webpack可以支持打包的文件。

chunk:编译完成准备输出时,webpack 将module 按特定规则组成的一个个 chunk
bundle:webpack 处理好chunk文件后,生成运行在浏览器中的代码
SplitChunks 插件是什么呢
简单的来说就是 Webpack 中一个提取或分离代码的插件,主要作用是提取公共代码,防止代码被重复打包,拆分过大的js文件,合并零散的js文件。
提到前端优化,提取公共代码是必不可少的手段。
在 Webpack 出现前,提取公共代码是人为去处理,而 SplitChunks 插件的作用就是通过配置让 Webpack 去帮你提取公共代码。SplitChunksPlugin 默认配置适用大部分场景。
打包默认情况下只会影响按需加载模块,因为对初始块也进行优化打包会影响 HTML 中的 script 标签数,增加请求数。
默认情况(webpack 的默认配置)下 webpack 会根据下述条件自动进行代码块分割:
- 共享模块(至少被引用 2次)或者 node_modules 模块
- 新代码块大于 20kb(min+gziped之前的体积)
- 按需加载块时的最大并行请求数将低于或等于 30
- 初始页面加载时的最大并行请求数将低于或等于 30
- 同步加载的模块:通过 import xxx 或 require(‘xxx’) 加载的模块。
- 异步加载的模块:通过 import(‘xxx’) 或 require([‘xxx’],() =>{}) 加载的模块。
1. 设置 chunks: initial || all 都可以提取出第三方库。但是它是把所有第三库提取出来,所以我们在只提取 react 和 react-dom 的情况下,需要自定义一个 cacheGroup。
- // webpack.config.js
- optimization: {
- splitChunks: {
- chunks: 'all',
- cacheGroups: {
- react: {
- name: 'react',
- test: /[\\/]node_modules[\\/](react|react-dom)[\\/]/,
- }
- }
- }
- }
安装 webpack-bundle-analyzer, 可以查看打包体积情况,在package.json 中,npm run build 的地方写一个 --report 就会在打包文件中生成一个 report.html, 打开可以看到打包体积情况。 "build": "vue-cli-service build --report"
2. 比如发现chunk-vendors.js的大小有点大了,有1.91MB,还是项目初始化时需要加载的 js 文件,大小过大会导致首屏加载时间过长。
要优化一下,两种方法:可以用SplitChunks优化。
例如要把element从chunk-vendors.js提取出来,就在cacheGroups 进行对应配置:
- chainWebpack(config) {
- config.when(process.env.NODE_ENV != 'development',
- config => {
- config.optimization.splitChunks({
- chunks: 'all',
- cacheGroups: {
- // 第三方组件
- libs: {
- // 指定chunks名称
- name: 'chunk-libs',
- //符合组的要求就给构建venders
- test: /[\\/]node_modules[\\/]/,
- //priority:优先级:数字越大优先级越高,因为默认值为0,所以自定义的一般是负数形式,决定cacheGroups中相同条件下每个组执行的优先顺序。
- priority: 10,
- // 仅限于最初依赖的第三方
- chunks: 'all'
- },
- elementUI: {
- // 将elementUI拆分为单个包
- name: 'chunk-elementUI',
- // 重量需要大于libs和app,否则将打包到libs或app中
- priority: 20,
- // 为了适应cnpm
- test: /[\\/]node_modules[\\/]_?element-ui(.*)/
- },
- //公共组件
- // commons: {
- // name: 'chunk-commons',
- // // can customize your rules
- // test: resolve('src/components'),
- // minChunks: 3,
- // priority: 30,
- // //这个的作用是当前的chunk如果包含了从main里面分离出来的模块,则重用这个模块,这样的问题是会影响chunk的名称。
- // reuseExistingChunk: true,
- // //最大初始化加载次数,一个入口文件可以并行加载的最大文件数量,默认3
- // maxInitialRequests: 3,
- // //表示在分离前的最小模块大小,默认为0,最小为30000
- // minSize: 0
- // },
- }
- })
- })
-
- }
webpack5 默认情况下只对异步模块做打包优化,额外的打包必须满足 4 个条件(webpack 的默认配置,可修改)。根据需求可调整为只对初始模块做打包优化,或者初始和异步模块一起优化。同时可配置自己的打包规则。
简而言之:chunks 控制打包作用范围,其他控制打包规则。
webpack5 的 splitChunks 功能是比较强大的,不过推荐还是使用默认模式,或者提取一下第三方库。