美文网首页
webpack CommonsChunkPlugin与Split

webpack CommonsChunkPlugin与Split

作者: codeflame | 来源:发表于2019-06-21 17:00 被阅读0次

    基础

    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里,但省略了),这样分析比较清楚。 良心作图2
    图解2:第一个new CommonsChunkPlugin那个执行完成后,如图所示。有7个chunk,其中a-b-c.js和admin.js被抽出放到admin-commons中 良心作图3

    图解3:minChunks为2,即重复引用两次即可抽出,显然a-b重复两次、a-b-c重复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与Split

          本文链接:https://www.haomeiwen.com/subject/mtjlfctx.html