demo08 关于SplitChunksPlugin

1.SplitChunksPlugin 介绍

从 webpack4 开始,用 SplitChunksPlugin 插件替换了 CommonsChunkPlugin 插件。 相对于 CommonsChunkPlugin ,SplitChunksPlugin 的使用更加方便和清晰。javascript

SplitChunksPlugin 是 webpack4 内置的开箱即用的代码块分离插件,webpack4 会根据你配置好 optimization.splitChunks 规则,进行代码分割,打包成不一样的代码块。这样的好处在于避免代码重复引用,减小代码体积,按需加载,从而使浏览器资源加载速度快,而且减小服务器的压力和带宽。html

SplitChunksPlugin 文档:www.webpackjs.com/plugins/spl…java

2.splitChunks参数配置

  • chunks (默认是async) :initialasyncall
  • minSize (默认是30000):新代码块最小体积(压缩以前),单位:字节(b)
  • minChunks(默认是1):代码块至少被引用的次数
  • maxInitialRequests (默认是3):入口处的最大并行请求数
  • maxAsyncRequests (默认是5):按需加载时最大的并行请求数
  • test (默认全部模块): 匹配须要处理的模块, 能够传的值类型: RegExp、String和Function
  • automaticNameDelimiter (默认是'~'): 打包分隔符
  • priority:缓存组打包的前后优先级

属性优先级 minSize > maxSize > maxAsyncRequests > maxInitialRequestwebpack

这里重要介绍一下 chunks 的三个属性 initialasyncallgit

  • async 只对对动态(异步)导入的模块进行分离
  • initial 对全部模块进行分离,若是一个模块既被异步引用,也被同部引用,那么会生成两个包
  • all 对全部模块进行分离,若是一个模块既被异步引用,也被同部引用,那么只会生成一个共享包

具体能够参考这篇文章: Webpack 4 Mysterious SplitChunks Plugingithub

3.安装相关依赖

经过 html-webpack-plugin 自动生成 index.htmlweb

npm install -D html-webpack-plugin
npm install -D webpack // html-webpack-plugin 依赖于 webpack
复制代码

3.目录结构

// `--` 表明目录, `-` 表明文件
  --demo08
    --src
      -app1.js
      -app2.js
      -module1.js
      -module2.js
      -module3.js
    -index.html
    -webpack.config.js
复制代码

src/module1.jsnpm

export const module1 = 'module1';
复制代码

src/module2.js浏览器

export const module2 = 'module2';
复制代码

src/module3.js缓存

export const module3 = 'module3';
复制代码

src/app1.js

import { module1 } from './module1';
import { module2 } from './module2';

// module1 module2 属于同步加载
console.log('app1: ', module1);
console.log('app1: ', module2);

// 经过require.ensure对module3.js进行加载调用(此写法在ts模式支持)
setTimeout(() => {
  require.ensure(
    [],
    function () {
      const module3 = require("./module3");
      console.log('app1: ', module3.module3);
    },
    "module3"
  );
}, 3000);

// // 异步加载的另外一种写法(此写法在ts模式下不支持)
// setTimeout(() => {
// import(/* webpackChunkName: 'module3'*/ "./module3").then(function (module3) {
// console.log(module3.module3);
// });
// }, 3000);
复制代码

src/app2.js

import { module1 } from './module1';
import { module2 } from './module2';
import { module3 } from './module3';

// module1 module2 module3 都属于同步加载(注意对比app1.js)
console.log('app2: ', module1);
console.log('app2: ', module2);
console.log('app2: ', module3);
复制代码

4.编写 webpack 配置文件

webpack.config.js

const path = require("path");
module.exports = {
  mode: 'production' || 'development',
  entry: {
    app1: "./src/app1.js",
    app2: "./src/app2.js"
  },
  output: {
    publicPath: __dirname + "/dist/", // 打包后资源文件的引用会基于此路径
    path: path.resolve(__dirname, "dist"), // 打包后的输出目录
    filename: "[name].bundle.js",
    chunkFilename: "[name].chunk.js"
  },
  optimization: {
    // runtimeChunk: "single", // 使用single模式,能够避免每个包都包含webpack的运行文件
    splitChunks: {
      cacheGroups: {
        modules: {
          chunks: "async" || "initial" || "all", // 三选一
          minChunks: 1, // 代码块至少被引用的次数
          maxInitialRequests: 3, // 设置最大的请求数
          minSize: 0, // 设置每一个chunk最小的大小,只有大于这个值,才会被打包进一个chunk
          automaticNameDelimiter: '~'
        }
      }
    }
  }
};
复制代码

5.执行打包命令

(默认你已经安装了全局 webpack 以及 webpack-cli )

webpack
复制代码

打包成功后,结果输出在 demo08 的dist目录下

在浏览器运行 dist/index.html,打开控制台能够观察异步加载模块的效果。

6.调试参数并验证输出结果

这里能够经过修改以上参数(好比 chunks , minChunks , minSize)的值来查看不一样的输出结果。

如上 webpack.config.js 配置文件,设置 minSize0 ,以及 minChunks1 以确保知足一个新块的条件。

当设置 chunksasync

webpack只对异步加载的模块进行分离,因此输出结果为:

app1.bundle.js
app2.bundle.js
modules~module3.chunk.js
复制代码

(注意以上例子中有两个入口文件 app1.js app2.js)

app1.js相关:

app1.bundle.js ( app1 主模块,而且包含 module1.js 和 module2.js)
modules~module3.chunk.js
复制代码

app2.js相关:

app2.bundle.js ( app2 主模块,而且包含 module1.js、module2.js 和 module3.js)
复制代码

当设置 chunksinitial

webpack对全部模块进行分离,若是一个模块既被异步引用,也被同部引用,那么会生成两个包,因此输出结果为:

app1.bundle.js
app2.bundle.js
module3.chunk.js
modules~app1.chunk.js
modules~app1~app2.chunk.js
modules~app2.chunk.js
复制代码

app1.js相关:

app1.bundle.js (app1主模块)
module3.chunk.js (包含 module3.js 异步加载模块)
modules~app1.chunk.js (包含app1独有的模块: 这里暂时没有)
modules~app1~app2.chunk.js (包含 module1.js 和 module2.js)
复制代码

app2.js相关:

app2.bundle.js (app2主模块)
modules~app2.chunk.js (包含app2独有的模块: 这里是module3.js)
modules~app1~app2.chunk.js (包含 module1.js 和 module2.js)
复制代码

当设置 chunksall

webpack对全部模块进行分离,若是一个模块既被异步引用,也被同部引用,那么只会生成一个共享包,因此输出结果为:

app1.bundle.js
app2.bundle.js
modules~app1.chunk.js
modules~app1~app2.chunk.js
modules~app2~module3.chunk.js
复制代码

app1.js相关:

app1.bundle.js ( app1 主模块)
modules~app1.chunk.js (包含 app1 独有的模块: 这里暂时没有)
modules~app1~app2.chunk.js (包含 module1.js 和 module2.js)
modules~app2~module3.chunk.js (包含 module3.js 模块,虽然名字没有 app1 ,可是能够经过测试知道,app1 是依赖此模块的,好比把此模块删除,而后在 index.html 中引入上面三个文件,查看控制台就能知道 app1 依赖此模块)
复制代码

app2.js相关:

app2.bundle.js ( app2 主模块)
modules~app1~app2.chunk.js (包含 module1.js 和 module2.js)
modules~app2~module3.chunk.js (包含 module3.js )
复制代码

7.bundle vs chunk

不知你注意到没有,以上打包结果中,app1 的主模块(app1.bundle.js)和app2的主模块(app2.bundle.js)的文件名包含的是 bundle,而其余模块包含的是 chunk。

bundle 代表该代码块包含有 webpack 运行时 的代码。而 chunk 则没有。 那你可能会问,这样 app1.bundle.js 和 app2.bundle.js 就包含了一样的 webpack 运行时代码,能够把这份 webpack 运行时的代码单独分离出来做为一个单独的块吗? 答案是能够的。

在 webpack.config.js 配置文件中添加如下属性便可:

runtimeChunk: "single"
复制代码

这样在以上 chunks 为 all 的示例中,输出的结果为:

app1.chunk.js
app2.chunk.js
modules~app1.chunk.js
modules~app1~app2.chunk.js
modules~app2~module3.chunk.js
runtime.bundle.js ( webpack 运行时模块)
复制代码

8.源码地址

demo 代码地址: github.com/SimpleCodeC…

仓库代码地址(及目录): github.com/SimpleCodeC…

参考文档:

Webpack 4 Mysterious SplitChunks

SplitChunksPlugin官方文档

相关文章
相关标签/搜索