码农的世界让前端飞Tech

webpack4系列教程(六):使用SplitChunksPlu

2019-01-10  本文已影响3人  前端小酱

传送门:

webpack4系列教程(一):初识webpack
webpack4系列教程(二):创建项目,打包第一个JS文件
webpack4系列教程(三):自动生成项目中的HTML文件
webpack4系列教程(四):处理项目中的资源文件(一)
webpack4系列教程(五):处理项目中的资源文件(二)

1. SplitChunksPlugin的概念

起初,chunks(代码块)和导入他们中的模块通过webpack内部的父子关系图连接.在webpack3中,通过CommonsChunkPlugin来避免他们之间的依赖重复。而在webpack4中CommonsChunkPlugin被移除,取而代之的是 optimization.splitChunks 和 optimization.runtimeChunk 配置项,下面展示它们将如何工作。

在默认情况下,SplitChunksPlugin 仅仅影响按需加载的代码块,因为更改初始块会影响HTML文件应包含的脚本标记以运行项目。

webpack将根据以下条件自动拆分代码块:

举例1:

// index.js

// 动态加载 a.js
import('./a')
// a.js
import 'vue'

// ...

打包之后的结果会创建一个包含 vue 的独立代码块,当包含 a.js 的原始代码块被调用时,这个独立代码块会并行请求进来。

原因:

我们这样做的原因是因为,vue代码并不像你的业务代码那样经常变动,把它单独提取出来就可以和你的业务代码分开缓存,极大的提高效率。

举例2:

// entry.js

import("./a");
import("./b");
// a.js
import "./helpers"; // helpers is 40kb in size

// ...
// b.js
import "./helpers";
import "./more-helpers"; // more-helpers is also 40kb in size

// ...

结果:将创建一个单独的块,其中包含./helpers它的所有依赖项。在导入调用时,此块与原始块并行加载。

原因:

2. SplitChunksPlugin的默认配置

以下是SplitChunksPlugin的默认配置:

splitChunks: {
    chunks: "async",
    minSize: 30000, // 模块的最小体积
    minChunks: 1, // 模块的最小被引用次数
    maxAsyncRequests: 5, // 按需加载的最大并行请求数
    maxInitialRequests: 3, // 一个入口最大并行请求数
    automaticNameDelimiter: '~', // 文件名的连接符
    name: true,
    cacheGroups: { // 缓存组
        vendors: {
            test: /[\\/]node_modules[\\/]/,
            priority: -10
        },
        default: {
            minChunks: 2,
            priority: -20,
            reuseExistingChunk: true
        }
    }
}

缓存组:

缓存组因该是SplitChunksPlugin中最有趣的功能了。在默认设置中,会将 node_mudules 文件夹中的模块打包进一个叫 vendors的bundle中,所有引用超过两次的模块分配到 default bundle 中。更可以通过 priority 来设置优先级。

chunks:

chunks属性用来选择分割哪些代码块,可选值有:'all'(所有代码块),'async'(按需加载的代码块),'initial'(初始化代码块)。

3. 在项目中添加SplitChunksPlugin

为了方便演示,我们先安装两个类库: lodash 和 axios,

npm i lodash axios -S

修改 main.js,引入 lodash 和axios 并调用相应方法:

import Modal from './components/modal/modal'
import './assets/style/common.less'
import _ from 'lodash'
import axios from 'axios'
const App = function () {
  let div = document.createElement('div')
  div.setAttribute('id', 'app')
  document.body.appendChild(div)
  let dom = document.getElementById('app')
  let modal = new Modal()
  dom.innerHTML = modal.template({
    title: '标题',
    content: '内容',
    footer: '底部'
  })
}
const app = new App()
console.log(_.camelCase('Foo Bar'))
axios.get('aaa')

使用SplitChunksPlugin不需要安装任何依赖,只需在 webpack.config.js 中的 config对象添加 optimization 属性:

optimization: {
    splitChunks: {
      chunks: 'initial',
      automaticNameDelimiter: '.',
      cacheGroups: {
        vendors: {
          test: /[\\/]node_modules[\\/]/,
          priority: 1
        }
      }
    },
    runtimeChunk: {
      name: entrypoint => `manifest.${entrypoint.name}`
    }
  }

配置 runtimeChunk 会给每个入口添加一个只包含runtime的额外的代码块,name 的值也可以是字符串,不过这样就会给每个入口添加相同的 runtime,配置为函数时,返回当前的entry对象,即可分入口设置不同的runtime。

我们再安装一个 webpack-bundle-analyzer,这个插件会清晰的展示出打包后的各个bundle所依赖的模块:

npm i webpack-bundle-analyzer -D

引入:

const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin

使用,在plugins数组中添加即可:

new BundleAnalyzerPlugin()

打包之后:

各个模块依赖清晰可见,打开 dist/index.html可见我们的代码顺利运行:

以上就是SplitChunksPlugin的基本用法,更多高级的配置大家可以继续钻研(比如多入口应用)。


本人才疏学浅,不当之处欢迎批评指正。

上一篇下一篇

猜你喜欢

热点阅读