webpack CommonsChunkPlugin与SplitChunksPlugin

基础

commons-chunk-plugin
split-chunks-plugin
即webpack的分包插件。CommonsChunkPlugin于4.0及以后被移除,使用SplitChunksPlugin替代。

chunk:块,指若干个js module的集合
bundle:形式上是块的集合,意义是代表一个可以运行的整体
chunk和bundle:what-are-module-chunk-and-bundle-in-webpack
比较难说明,搜的基本都是个人总结,官方描述也比较抽象。
就我个人总结来说,一个模块化的js文件就是一个模块,若干个js模块会打包成一个总的js文件,这个js文件称作bundle。但如果是多页面应用,往往会安排为一个html对应一个bundle,那么两个html的bundle之间重复的模块就是重复代码。此时我们会把这两个bundle重复的模块抽出来,称为common chunk,余下的两部分直接称作两个chunk。即此时一共有3个chunk,但依然只有两个bundle。
单页面应用中异步加载,或者单纯想分离出不变的第三方库,均可采用该手段进行优化。

入口chunk:entry里面的指定的入口,他们对应一个chunk并且key值就是chunk name


CommonsChunkPlugin

最基本使用

CommonsChunkPlugin基本选项:
name:选择一个chunk。该chunk存在则选中,不存在则新建。代表把下面的chunks他们的重复模块合并到这个chunk
chunks:chunk来源,不设置代表选择全部入口chunk
minChunks:被多少次重复引用时才抽出来。数量必须大于等于2,或者少于等于chunks的数量
请对照着官方示例直接上:

良心作图1

图解1:入口有6个,当然有6个chunk了。每个chunk都是js模块的集合,如pageA这个chunk就有4个模块{a-b,a-c,a-b-c,pageA},图里省略了一些路径和入口文件的那个模块(如pageA.js也在pageA这个chunk里,但省略了),这样分析比较清楚。

webpack CommonsChunkPlugin与SplitChunksPlugin_第1张图片
良心作图2

图解2:第一个new CommonsChunkPlugin那个执行完成后,如图所示。有7个chunk,其中a-b-c.js和admin.js被抽出放到admin-commons中

webpack CommonsChunkPlugin与SplitChunksPlugin_第2张图片
良心作图3

图解3:minChunks为2,即重复引用两次即可抽出,显然a-b重复两次、a-b-c重复3次,均被抽出

webpack CommonsChunkPlugin与SplitChunksPlugin_第3张图片
良心作图4

图解4:a-b-c抽出

最终,9个chunk,生成9个js文件。
至于“父子关系”,看图即可。假如我们要引入adminPageA.js,就要先引入admin-commons.js,因为他有部分代码在admin-commons.js;同理要引入admin-commons.js就要先引入commons.js,最终在html的导入写法如官方例子所示。

进阶使用

1.minChunks: Infinity有何用?无穷次重复引用才抽出?
明确第三方库 chunk。注意name的说明有说是存在则选择,chunks的说明有说不写则默认选中全部入口chunk,这说明可能会把入口chunk之间重复的模块抽到vendor(早已存在,包含"jquery", "other-lib"模块)。这里只是一个保证,自己能弄明白的时候这个可以换种写法或者直接整个省略不写。

2.childrenasync
弄懂这两个就算大成了,剩下的minSize、deepChildren自己猜都能猜到。
这里右转:webpack中ensure方法和CommonsChunkPlugin中的children选项
上面的例子都是基于require直接静态导入的,但是对于动态导入的require.ensure和动态import函数来说,情况比较特殊,因为他们是直接生成目标模块的chunk并挂在当前所在chunk下。如a是父亲,b、c是儿子,在动态引入情况下,b、c可能包含相同的模块。

childrenasync就是用来处理子chunk有重复模块的。
children:true表示chunks等于当前chunk的所有子chunk(你也可以手动chunks:["..."]来选择它的所有子chunk,前提是你要清晰地知道所有子chunk的chunk name),然后逻辑同上,把选中的chunks的重复模块抽出,合并到当前模块,换种新的说法就是把子chunk重复的模块抽出到父chunk。
async:true表示异步的,作为 options.name 的子模块,和 options.chunks 的兄弟模块被创建(官网的解释够鬼畜的)。简单来说,就是chunk的重复模块会被抽出,重新组合成一个新的chunk而不是合并到当前chunk。存在的意义基本上就是为上面那个children,作用是把子chunk重复模块抽出成新的chunk,不要合并到父chunk中


SplitChunksPlugin

不知道上面有没有绕晕你,反正是有点复杂的难说明的。因此webpack4.0后提供一个新的分包插件SplitChunksPlugin,让你可以开箱即用,高度抽象。

用法方面,直接当做webpack配置使用即可,不用再去new一个plugin

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
        }
    }
}

上面是默认配置,你的更改会被合并到该配置中。最外层的配置充当全局配置,可被cacheGroups中的配置给继承和局部覆盖。
这个不再需要我们去分析什么父子chunk、哪些chunk之间可能相同需要抽取等等。即使你硬要配置,也只用站在全局角度去考虑首屏静态加载的js文件最大数量maxInitialRequests、动态加载的最大js数量maxAsyncRequests等,比起CommonsChunkPlugin那坨东西舒服多了。
详细学习可右转:Webpack4之SplitChunksPlugin

你可能感兴趣的:(webpack CommonsChunkPlugin与SplitChunksPlugin)