webpack4之splitChunks.maxAsyncRequests

概要

这个配置用来控制按需引入的包中的直接引入的包的打包。他表示按需引入的包中并行请求的最大数量。

一开始听起来肯定是大脑一片蒙蒙的感觉,不过其实很简单,可以理解为:当整个项目打包完之后,一个按需加载的包最终被拆分成n个包,maxAsyncRequests就是用来限制n的最大值。

接下来,还是按照老规矩,通过一系列的例子来实践一下。

准备工作

  1. 目录
root
——dist(打包之后的文件夹)
——node_modules(下载的包)
——src(项目脚本目录)
————entry(入口点脚本)
————modules(入口点中引入的模块)
——package.json(包管理文件)
——webpack.config.js(webpack配置文件)
  1. webpack配置
const path = require('path')
const { CleanWebpackPlugin } = require('clean-webpack-plugin');

module.exports = {
  entry: {
    entry1: './src/entry/entry1.js',
    entry2: './src/entry/entry2.js'
  },
  plugins: [
    new CleanWebpackPlugin()
  ],
  output: {
    filename: '[name].bundle.js',
    path: path.resolve(__dirname, 'dist')
  },
  optimization: {
    splitChunks: {
      chunks: 'all',
      maxAsyncRequests: 3,
      minSize: 1,
      cacheGroups: {
        vendors: {
          test: /[\\/]node_modules[\\/]/,
          priority: -10
        },
        default: {
          minChunks: 1,
          priority: -20,
          reuseExistingChunk: true
        }
      }
    }
  }
  // default config
  // optimization: {
  //   splitChunks: {
  //     chunks: 'async',
  //     minSize: 30000,
  //     minChunks: 1,
  //     maxAsyncRequests: 5,
  //     maxInitialRequests: 3,
  //     automaticNameDelimiter: '~',
  //     automaticNameMaxLength: 30,
  //     name: true,
  //     cacheGroups: {
  //       vendors: {
  //         test: /[\\/]node_modules[\\/]/,
  //         priority: -10
  //       },
  //       default: {
  //         minChunks: 2,
  //         priority: -20,
  //         reuseExistingChunk: true
  //       }
  //     }
  //   }
  // }
}
  1. package.json
{
  "name": "test",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "webpack"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "clean-webpack-plugin": "^3.0.0",
    "webpack": "^4.41.2",
    "webpack-cli": "^3.3.10"
  }
}

案例

接下来,通过几个简单的案例,来分析maxAsyncRequests配置的控制规则。

  1. demo1
################################
webpack.config.js:

splitChunks.maxAsyncRequests设为2

################################
modules/add.js:

export default function add (a, b) {
  return a + b
}

################################
modules/subtract.js

export default function subtract (a, b) {
  return a - b
}

################################
modules/mutiply.js

export default function mutiply (a, b) {
  return a * b
}

################################
modules/module.js

import add from './add'
import subtract from './subtract'
import multiply from './multiply'

export default function () {
  console.log(add(3, 4) + subtract(10, 5) + multiply(1, 2))
}

################################
entry/entry1.js:

import('../modules/module').then(f => {
  console.log('index', f())
})

################################
entry/entry2.js:

import add from '../modules/add'
import subtract from '../modules/subtract'
import multiply from '../modules/multiply'

console.log('index', add(1, 2) + subtract(4, 2) + multiply(1, 2))

通过npm run build进行打包,结果如下:

Hash: 699d2402a2a59dfa24c3
Version: webpack 4.41.5
Time: 85ms
Built at: 2020/01/19 上午9:28:13
                   Asset       Size  Chunks             Chunk Names
             0.bundle.js  333 bytes       0  [emitted]  
             5.bundle.js  211 bytes       5  [emitted]  
default~entry1.bundle.js  165 bytes       1  [emitted]  default~entry1
default~entry2.bundle.js  196 bytes       2  [emitted]  default~entry2
        entry1.bundle.js   2.22 KiB       3  [emitted]  entry1
        entry2.bundle.js   1.47 KiB       4  [emitted]  entry2
Entrypoint entry1 = default~entry1.bundle.js entry1.bundle.js
Entrypoint entry2 = 0.bundle.js default~entry2.bundle.js entry2.bundle.js
[0] ./src/modules/add.js 54 bytes {0} [built]
[1] ./src/modules/subtract.js 59 bytes {0} [built]
[2] ./src/modules/multiply.js 59 bytes {0} [built]
[3] ./src/modules/module.js 183 bytes {5} [built]
[4] ./src/entry/entry1.js 70 bytes {1} [built]
[5] ./src/entry/entry2.js 185 bytes {2} [built]

我们会发现,add.js、subtract.js、multiply.js被打包到0.bundle.js,相当于entry1中按需引入的module/module.js包最终被拆分成0.bundle.js和5.bundle.js,刚刚好等于我们配置的最大上限值2。(这里注意下,webpack发现entry1中引入的module.js和entry2都直接引入了add.js、subtract.js和multiply.js,所以它很只能地将这三个包打包进同一个文件中,而不是分别单独打包。)

  1. demo2.js
################################
webpack.config.js:

splitChunks.maxAsyncRequests设为1

################################
modules/add.js:

export default function add (a, b) {
  return a + b
}

################################
modules/subtract.js

export default function subtract (a, b) {
  return a - b
}

################################
modules/mutiply.js

export default function mutiply (a, b) {
  return a * b
}

################################
modules/module.js

import add from './add'
import subtract from './subtract'
import multiply from './multiply'

export default function () {
  console.log(add(3, 4) + subtract(10, 5) + multiply(1, 2))
}

################################
entry/entry1.js:

import('../modules/module').then(f => {
  console.log('index', f())
})

################################
entry/entry2.js:

import add from '../modules/add'
import subtract from '../modules/subtract'
import multiply from '../modules/multiply'

console.log('index', add(1, 2) + subtract(4, 2) + multiply(1, 2))

只是将maxAsyncRequests设为1,然后再次打包,结果如下:

Hash: 752b64e3f762dc224b3b
Version: webpack 4.41.5
Time: 84ms
Built at: 2020/01/19 上午9:38:39
                   Asset       Size  Chunks             Chunk Names
             4.bundle.js  482 bytes       4  [emitted]  
default~entry1.bundle.js  143 bytes       0  [emitted]  default~entry1
default~entry2.bundle.js  469 bytes       1  [emitted]  default~entry2
        entry1.bundle.js   2.22 KiB       2  [emitted]  entry1
        entry2.bundle.js   1.47 KiB       3  [emitted]  entry2
Entrypoint entry1 = default~entry1.bundle.js entry1.bundle.js
Entrypoint entry2 = default~entry2.bundle.js entry2.bundle.js
[0] ./src/modules/add.js 54 bytes {1} {4} [built]
[1] ./src/modules/subtract.js 59 bytes {1} {4} [built]
[2] ./src/modules/multiply.js 59 bytes {1} {4} [built]
[3] ./src/modules/module.js 183 bytes {4} [built]
[4] ./src/entry/entry1.js 70 bytes {0} [built]
[5] ./src/entry/entry2.js 185 bytes {1} [built]

add.js、subtract.js、multiply.js并没有被单独打包出来,分别包含于4.bundle.js和default~entry2.bundle.js中。这恰好对应了我们配置的1,因为最大值为1,如果同demo1一样将add.js、subtract.js和multiply.js单独打包进一个文件中,相当于一个module被拆分成2个文件(即 > 1)。

  1. demo3
################################
webpack.config.js:

splitChunks.maxAsyncRequests设为2

同时entry入口新增entry3.js,如下:

entry: {
    entry1: './src/entry/entry1.js',
    entry2: './src/entry/entry2.js',
    entry3: './src/entry/entry3.js',
}

################################
modules/add.js:

export default function add (a, b) {
  return a + b
}

################################
modules/subtract.js

export default function subtract (a, b) {
  return a - b
}

################################
modules/mutiply.js

export default function mutiply (a, b) {
  return a * b
}

################################
modules/module.js

import add from './add'
import subtract from './subtract'
import multiply from './multiply'

export default function () {
  console.log(add(3, 4) + subtract(10, 5) + multiply(1, 2))
}

################################
entry/entry1.js:

import('../modules/module').then(f => {
  console.log('index', f())
})

################################
entry/entry2.js:

import add from '../modules/add'
import subtract from '../modules/subtract'
import multiply from '../modules/multiply'

console.log('index', add(1, 2) + subtract(4, 2) + multiply(1, 2))

################################
entry/entry3.js:

import add from '../modules/add'
import subtract from '../modules/subtract'

console.log('index', add(1, 2) + subtract(4, 2))

npm run build打包后,结果如下:

Hash: fbf4c99a34e2c4080633
Version: webpack 4.41.5
Time: 83ms
Built at: 2020/01/23 上午11:39:36
                   Asset       Size  Chunks             Chunk Names
             0.bundle.js  242 bytes       0  [emitted]  
             7.bundle.js  302 bytes       7  [emitted]  
default~entry1.bundle.js  165 bytes       1  [emitted]  default~entry1
default~entry2.bundle.js  289 bytes       2  [emitted]  default~entry2
default~entry3.bundle.js  172 bytes       3  [emitted]  default~entry3
        entry1.bundle.js   2.22 KiB       4  [emitted]  entry1
        entry2.bundle.js   1.47 KiB       5  [emitted]  entry2
        entry3.bundle.js   1.47 KiB       6  [emitted]  entry3
Entrypoint entry1 = default~entry1.bundle.js entry1.bundle.js
Entrypoint entry2 = 0.bundle.js default~entry2.bundle.js entry2.bundle.js
Entrypoint entry3 = 0.bundle.js default~entry3.bundle.js entry3.bundle.js
[0] ./src/modules/add.js 54 bytes {0} [built]
[1] ./src/modules/subtract.js 59 bytes {0} [built]
[2] ./src/modules/multiply.js 59 bytes {2} {7} [built]
[3] ./src/modules/module.js 183 bytes {7} [built]
[4] ./src/entry/entry1.js 70 bytes {1} [built]
[5] ./src/entry/entry2.js 185 bytes {2} [built]
[6] ./src/entry/entry3.js 171 bytes {3} [built]

其中add.js和subtract.js被单独打包进0.bundle.js,保证了module.js被拆分成了2个文件。(我们配置的上限为2)

假设我们没有限制,可以想到的是,add.js和subtract.js被拆分到一个文件中,multiply.js被拆分到一个文件中,所以我们会有这样一个疑惑,就是multiply.js为什么没有被拆出来,而是add.js、subtract.js被拆分出来。个人的猜想有两点:一个是add.js、subtract.js在三个入口点中均引入,而multiply.js在两个入口点中被引入;另外一个是add.js、subtract.js拆分出来的包肯定比单独multiply.js一个文件大。

为了得出webpack相应的打包规则,我们将multiply.js添加很多注释,使得其大小大于add.js和subtract.js大小总和。打包之后我们会发现结果和上面是一样的,所以可以得出:对于可能被打包的两种情况,被引入更多次的那个包会被优先打包出来。

那么引入的次数如果是一样的,那么是不是体积更大的会优先被打包出来呢,我们也可以测试一下。基于刚刚对demo3中multiply.js添加注释的代码,对于entry2.js只引入add.js,对于entry3.js只引入multiply.js,这个时候的打包结果为multiply.js被单独打包出来。

综上,我们得出的结论是:

a. 如果对于单独打包出来的模块有两种可能,被多次引入的那个包会被优先打包出来;
b. 同样的情况,如果两种情况下模块被引用的次数相同,体积大的那个模块或多个模块集会被打包出来;

注:如果两种情况下,情况一只包含一个模块,情况二则包含两个模块,并且两种情况下被引入的次数也是相同的,那么打包规则还是按照上面的b规则。

  1. demo4
################################
webpack.config.js:

在基于demo3的基础上将splitChunks.maxAsyncRequests设为3

################################
modules/add.js:

export default function add (a, b) {
  return a + b
}

################################
modules/subtract.js

export default function subtract (a, b) {
  return a - b
}

################################
modules/mutiply.js

export default function mutiply (a, b) {
  return a * b
}

################################
modules/module.js

import add from './add'
import subtract from './subtract'
import multiply from './multiply'

export default function () {
  console.log(add(3, 4) + subtract(10, 5) + multiply(1, 2))
}

################################
entry/entry1.js:

import('../modules/module').then(f => {
  console.log('index', f())
})

################################
entry/entry2.js:

import add from '../modules/add'
import subtract from '../modules/subtract'
import multiply from '../modules/multiply'

console.log('index', add(1, 2) + subtract(4, 2) + multiply(1, 2))

################################
entry/entry3.js:

import add from '../modules/add'
import subtract from '../modules/subtract'

console.log('index', add(1, 2) + subtract(4, 2))

npm run build打包后,结果如下:

Hash: a3554617a9e78396ebfd
Version: webpack 4.41.5
Time: 272ms
Built at: 2020/01/23 上午11:43:49
                   Asset       Size  Chunks             Chunk Names
             0.bundle.js  242 bytes       0  [emitted]  
             1.bundle.js  153 bytes       1  [emitted]  
             7.bundle.js  211 bytes       7  [emitted]  
default~entry1.bundle.js  172 bytes       2  [emitted]  default~entry1
default~entry3.bundle.js  172 bytes       3  [emitted]  default~entry3
        entry1.bundle.js   2.22 KiB       4  [emitted]  entry1
        entry2.bundle.js    1.6 KiB       5  [emitted]  entry2
        entry3.bundle.js   1.47 KiB       6  [emitted]  entry3
Entrypoint entry1 = default~entry1.bundle.js entry1.bundle.js
Entrypoint entry2 = 0.bundle.js 1.bundle.js entry2.bundle.js
Entrypoint entry3 = 0.bundle.js default~entry3.bundle.js entry3.bundle.js
[0] ./src/modules/add.js 54 bytes {0} [built]
[1] ./src/modules/subtract.js 59 bytes {0} [built]
[2] ./src/modules/multiply.js 59 bytes {1} [built]
[3] ./src/entry/entry2.js 185 bytes {5} [built]
[4] ./src/modules/module.js 183 bytes {7} [built]
[5] ./src/entry/entry1.js 70 bytes {2} [built]
[6] ./src/entry/entry3.js 171 bytes {3} [built]

add.js和subtract.js被单独打包进0.bundle.js,multiply.js被单独打包进1.bundle.js中。

如果继续将maxAsyncRequests配置项继续增大,结果还是一样。

这里将maxAsyncRequests设置为3,也就表示按需引入的module.js最多只能被拆分成三个bundle。

注:上面的打包结果我们会发现和之前的有些不一样,default.entry2.bundle.js没有被打包出来,这里主要是跟maxInitialRequests这个配置有关,该配置默认为3,这就表示单个入口点最多能被拆分的数量,上面这种情况,已经被拆分出0.bundle.js、1.bundle.js和entry2.js,数目已经达到3,default.entry2.bundle.js自然不会被打包出来。

  1. demo5
################################
webpack.config.js:

splitChunks.maxAsyncRequests设为2

基于demo3新增一个入口点,例如:

entry: {
    entry1: './src/entry/entry1.js',
    entry2: './src/entry/entry2.js',
    entry3: './src/entry/entry3.js',
    entry4: './src/entry/entry4.js',
}

################################
modules/add.js:

export default function add (a, b) {
  return a + b
}

################################
modules/subtract.js

export default function subtract (a, b) {
  return a - b
}

################################
modules/mutiply.js

export default function mutiply (a, b) {
  return a * b
}

################################
modules/module.js

import add from './add'
import subtract from './subtract'
import multiply from './multiply'

export default function () {
  console.log(add(3, 4) + subtract(10, 5) + multiply(1, 2))
}

################################
entry/entry1.js:

import('../modules/module').then(f => {
  console.log('index', f())
})

################################
entry/entry2.js:

import add from '../modules/add'
import subtract from '../modules/subtract'
import multiply from '../modules/multiply'

console.log('index', add(1, 2) + subtract(4, 2) + multiply(1, 2))

################################
entry/entry3.js:

import add from '../modules/add'
import subtract from '../modules/subtract'

console.log('index', add(1, 2) + subtract(4, 2))

################################
entry/entry4.js:

import add from '../modules/add'
import subtract from '../modules/subtract'

console.log('index', add(1, 2) + subtract(4, 2))

打包后,结果如下:

Hash: 0edbe3d934d97c0d8908
Version: webpack 4.41.5
Time: 95ms
Built at: 2020/01/23 下午1:58:34
                   Asset       Size  Chunks             Chunk Names
             0.bundle.js  242 bytes       0  [emitted]  
             9.bundle.js  302 bytes       9  [emitted]  
default~entry1.bundle.js  165 bytes       1  [emitted]  default~entry1
default~entry2.bundle.js  289 bytes       2  [emitted]  default~entry2
default~entry3.bundle.js  172 bytes       3  [emitted]  default~entry3
default~entry4.bundle.js  172 bytes       4  [emitted]  default~entry4
        entry1.bundle.js   2.22 KiB       5  [emitted]  entry1
        entry2.bundle.js   1.47 KiB       6  [emitted]  entry2
        entry3.bundle.js   1.47 KiB       7  [emitted]  entry3
        entry4.bundle.js   1.47 KiB       8  [emitted]  entry4
Entrypoint entry1 = default~entry1.bundle.js entry1.bundle.js
Entrypoint entry2 = 0.bundle.js default~entry2.bundle.js entry2.bundle.js
Entrypoint entry3 = 0.bundle.js default~entry3.bundle.js entry3.bundle.js
Entrypoint entry4 = 0.bundle.js default~entry4.bundle.js entry4.bundle.js
[0] ./src/modules/add.js 54 bytes {0} [built]
[1] ./src/modules/subtract.js 59 bytes {0} [built]
[2] ./src/modules/multiply.js 59 bytes {2} {9} [built]
[3] ./src/modules/module.js 183 bytes {9} [built]
[4] ./src/entry/entry1.js 70 bytes {1} [built]
[5] ./src/entry/entry2.js 185 bytes {2} [built]
[6] ./src/entry/entry3.js 171 bytes {3} [built]
[7] ./src/entry/entry4.js 171 bytes {4} [built]

其实就和demo3一样,add.js和subtract.js被单独打包到0.bundle.js,假如将maxAsyncRequests设置为3,效果和demo4一样。

上面的demo我们都是建立在chunks设置成all的情况下,如果设置成async,maxAsyncRequests配置还有效吗?当然是有效的。

总结

  • maxAsyncRequests用来表示按需加载的模块其能拆分的最大数量;
  • 如果对于单独打包出来的模块有两种可能,被多次引入的那个包会被优先打包出来;
  • 同样的情况,如果两种情况下模块被引用的次数相同,体积大的那个模块或多个模块集会被打包出来;
  • 该配置对于chunks为async和all情况下均可行,对于initial无效;
webpack4之splitChunks.maxAsyncRequestswebpack4之splitChunks.maxAsyncRequests YaoDeBiAn 发布了71 篇原创文章 · 获赞 91 · 访问量 14万+ 私信 关注
上一篇:C# 计算两个日期的时间间隔


下一篇:php – MySQL“NOT IN”查询不起作用