webpack代码分割之SplitChunksPlugin和魔法注释

webpack.jpg

写在前面

我们在上篇的文章中,介绍了Code Splitting,其中有通过SplitChunksPlugin加同步引入的方式进行代码分割,和通过异步加载的方式让webpack自动帮我们完成代码分割,上篇中,我们也是主要对代码分割的概念和方式做了介绍和操作,其中提到的SplitChunksPlugin和异步加载只是简单使用了一下,这篇我们将详细学习SplitChunksPlugin的参数配置和异步加载。

异步加载中的魔法注释

我们再来看这段代码

function getComponent () {
    return import('lodash').then(({ default: _ }) => {
        var element = document.createElement('div')
        element.innerHTML = _.join(['a', 'b', 'c'])
        return element
    })
}

getComponent().then(element => {
    document.body.appendChild(element)
})

其中lodash是一种通过异步引入的,那么webapck在打包的时候就会自动帮我们把代码做分割,我们知道现在lodash会生成一个0.js的文件,其实这是一个ID,那我们想把这个名字换成一个相应的英文名字,那该怎么做呢?这就是魔法注释。我们将动态引入改成下面这样

import(/* webpackChunkName:"lodash" */'lodash')

代表我们将异步引入的文件,打包后生成名为“lodash”的文件
再打包试一下,这时候会发现目录变成了这样

|--dist
  |--index.html
  |--main.js
  |--vendors~lodash.js

(对于一些webapck 低版本v4可能达到预期,这时候,你需要装一个官方的babel插件,让异步加载来支持这种魔法注释(@babel/plugin-syntax-dynamic-import))
这时候有人就会疑问了“我们明明给他的文件明明是“lodash”为什么打包出来的文件前面加入了一个‘vendors~呢?’”加下来大家就和我一起学习插件SplitChunksPlugin

SplitChunksPlugin

在上篇中,我们曾简单用了它一下,体验了一下code splitting,但其实他的配置内容有很多,这里我将对这个插件做详细的配置讲解,这是官网对他的介绍,同学们也可以参考官网SplitChunksPlugin
我们将webpack.common.js中的optimization项先改成下面这样,这次再对刚才的项目做打包看一下。

optimization: {
  splitChunks: {
    chunks: 'all',
      cacheGroups: {
        vendors: false,
        default: false
        }
    }
},

我们发现打包文件中vendors~lodash.js变成了lodash。这说明
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
        }
    }
}

我们将vendors和default都置为false,以免对其他配置项进行影响。

chunks:initialasyncall

chunks有三个值,意思是我们对哪种代码做分割,有异步,有同步,有所有类型,上面的默认配置中他的值是async,意思是这个插件只对异步加载的模块生效,下面我们将index.js中的模块改成同步引入

import _ from 'lodash'
var element = document.createElement('div')
element.innerHTML = _.join(['a', 'b', 'c'])
document.body.appendChild(element)

打包一下,大家可以看到,对于同步的模块引入是没有进行代码分割的,下面我们将chunks的值改为all,再打包一下,发现还是没有生效哈,这是因为,当我们将chunks的值设为all的时候,webpack会知道我们将对同步引入的模块进行打包,但业务代码中各种逻辑的引入其实一般都是同步引入的方式,这样就会给分割带来困难,于是他会跳转到cacheGroups中查看相关配置,那现在我们先将cacheGroups.vendors改为官网默认的

vendors: {
    test: /[\\/]node_modules[\\/]/,
    priority: -10
},

这时候再打包,发现打包目录变成了下面这样

|--dist
  |--index.html
  |--main.js
  |--vendors~main.js

意思是我们代码分割成功了,看vendors.main.js中,也是对lodash库的引用。vendors~main.js前面的vendors代表,我们的lodash符合vendors组的要求,所以前缀就变成了这个组的名字,其中的main代表这个库的引入是入口是main.js,也就是其对应的index.js。

cacheGroups.vendors

有时候我们希望我们将所有的类库都打包到一个'vendors.js'的文件中,这时候,我们就可以在vendors.filename中配置

vendors: {
    test: /[\\/]node_modules[\\/]/,
    priority: -10,
    filename: 'vendors.js'
},

这时候打包看一下。文档目录变成了这样

|--dist
  |--index.html
  |--main.js
  |--vendors.js

这样配置的意思是,一旦我们对同步代码做风格,他就会到cacheGroups里面找匹配,一旦匹配了相应的组,就会按照这个组的一些配置做相应的分割,他和chunks是配合使用的

minSize

当引入的库大于该值时才做代码分割,小于的话就不做大吗风格了,大家可以在这里把minSize设的特别大来验证一下

cacheGroups.default

这里我们新建一个test.js导出一个特别简单的内容,并将minSize改为0,来打包测试一下

export default {
    name: 'hello webpack'
}

index.js

import test from './test'
console.log(test.name)

现在的内容和你简单,按照上面minsize的配置,我们将其设为0,他是理应会执行代码分割的,但打包发现,他并没有按照预期去执行代码分割,这是因为webpack在打包时,因其满足minsize,又是代码,就会去执行cacheGroups中的代码,但他又不符合vendors组的规则(不是node_modules下的内容),所以就没有将其正常风格,这时候我们就需要用到cacheGroups.default,我们先将官网的默认配置拷贝过来,去掉cacheGroups.default.minChunks参数,执行打包,我们发现,打包目录变成了这样

|--dist
  |--index.html
  |--main.js
  |--default~main.js

其打包的命名规则和配置规则和cacheGroups.vendors相同。我们也可以给其设置一个filename。

minChunks

minChunks代表一个模块被应用了多少次的时候才进行代码分割。

maxAsyncRequests

代表同时加载的模块数最大值,这里的默认值是5,假如我们有10个模块文件被分割,这里会将前五个模块分割,其他的就不分割了,一般取默认配置

maxInitialRequests

代表整个网站首页加载的时候,入口文件最大的加载数,如果入口文件引入的模块数大于这个值,其他的将不会被做代码分割,一般取默认配置

automaticNameDelimiter

代表组和文件名之前的连接符

name

设置为true代表我们在组中设置的文件名有效,一般不改默认配置

cacheGroups.*.priority

代表组的权重,有的模块会同事满足多个组的规则,比如我们现在的lodash就同时满足vendorsdefault两个组的要求,这时候就需要一个权重值来让模块优先执行哪个组的打包。

cacheGroups.**.reuseExistingChunk

默认为true,遇到多个模块相互引用的时候,当一个模块被重复使用,那么将不会重新打包,将使用之前打包的路径

写在最后

本篇也是比较详细的介绍了SplitChunksPlugin这个插件,其实其内容还远比文章中介绍的多,有兴趣的同学可以去官网再去查阅相关的资料。用好SplitChunksPlugin你的代码打包将变的效率更高,学习一下吧~

你可能感兴趣的:(webpack代码分割之SplitChunksPlugin和魔法注释)