webpack之splitChunks代码分割

1,364 阅读4分钟

首先如果不做任何处理,我们的webpack会将所有的js打包到一个文件中。

所以我们要做代码分割,常见的有三种方式:

  1. 使用entry配置手动分离。
  2. import()动态导入。
  3. 利用splitChunks。

那么我们需要明白一点:无论splitChunks如何配置,只要是动态引入的模块(页面),都是会被单独用一个文件来存放的。其次,通常情况下,不用动态引入,所有页面就都在一个js包里,动态引入了就一个页面一个js包。

splitChunks是作为一个配置对象传入的(chunks分割规则嘛,一个chunks就是一个js文件),splitChunks的默认配置为:

    // 表示选择哪些 chunks 进行分割,可选值有:async,initial和all
    chunks: "async",
    // 表示新分离出的chunk必须大于等于minSize,默认为30000,约30kb。
    minSize: 30000,
    // 表示一个模块至少应被minChunks个chunk所包含才能分割。默认为1。
    minChunks: 1,
    // 表示按需加载文件时,并行请求的最大数目。默认为5。
    maxAsyncRequests: 5,
    // 表示加载入口文件时,并行请求的最大数目。默认为3。
    maxInitialRequests: 3,
    // 表示拆分出的chunk的名称连接符。默认为~。如chunk~vendors.js
    automaticNameDelimiter: '~',
    // 设置chunk的文件名。默认为true。当为true时,splitChunks基于chunk和cacheGroups的key自动命名。
    name: true,
    // cacheGroups 下可以可以配置多个组,每个组根据test设置条件,符合test条件的模块,就分配到该组。模块可以被多个组引用,但最终会根据priority来决定打包到哪个组中。默认将所有来自 node_modules目录的模块打包至vendors组,将两个以上的chunk所共享的模块打包至default组。
    cacheGroups: {
        vendors: {
            test: /[\\/]node_modules[\\/]/,
            priority: -10
        },
        // 
    default: {
            minChunks: 2,
            priority: -20,
            reuseExistingChunk: true
        }
    }
}

chunks

我们的chunks可分为两类:1.首页加载需要用到的(同步包,首页js) 2.到用的时候才需要加载的包(异步包,其他普通页面js)

chunks的值有:async(默认)、initial、all。

这三个值的意思是,只对异步包进行拆分,只对同步包进行拆分,对所有包都拆分。

例如说:首页main.js中动态引入a.js页面,a.js中引入vue。

  • 当chunks为async时,会分为三个包,一个同步的app.js,一个异步页面包1.js,一个vue的依赖包2.js(2.js就是被分出来的一个包)。
  • 当chunks为initial时,只会分为两个包,一个同步的app.js,一个异步页面包1.js。但如果我们改变题目,是main.js引入的vue,a.js中未引入,那么app.js会拆分成app.js和2.js了。
  • 当chunks为all时,就很简单了,不论vue是index.js中引入,还是a.js中引入,都会被单独拆分出来。

minSize、maxInitialRequests、maxAsyncRequests

minSize: 分出来的包的最小大小,就是新包要比这个值大,才能分出来。

maxInitialRequests:最大同步包个数,就是你首页加载,需要的包不能超过这个数。

maxAsyncRequests:一次异步,最大异步包个数,就是你一个普通页面加载,需要的包不能超过这个数。

不满足这些条件的话,包是不允许分出来的。

minChunks

就是一个模块最少被几个chunks依赖才允许分离出来,默认是1。

例子:拿chunks中的例子来说,a.js中引入vue,那么vue属于被依赖了一次,minChunks为1满足条件,可以将vue单独作为包分离出来,但是如果minChunks为2就不行了,至少还要有其他chunks中依赖vue,才可以被分离出来。

cacheGroups

自定义chunk包,也就是说我们可以自定义chunks包,将符合条件的代码(或模块),从别的包里分出来放这里面。

cacheGroups继承 splitChunks 里的所有属性的值,如 chunksminSizeminChunksmaxAsyncRequestsmaxInitialRequestsautomaticNameDelimitername ,我们还可以在 cacheGroups 中重新赋值,覆盖 splitChunks 的值。另外,还有一些属性只能在 cacheGroups 中使用:testpriorityreuseExistingChunk

通过 test 条件对模块进行过滤,符合条件的模块分配到相同的组, priority优先级,同时满足两个的筛选条件的模块,根据优先级来决定放到哪个chunks中,priority越大,优先级越高。

cacheGroups 有两个默认的组,一个是 vendors,将所有来自 node_modules 目录的模块放进入;一个 default(vue3叫common了),包含了由两个以上的 chunk 所共享的模块。

名字默认由 cacheGroups 中组的 key + 源chunk名组成(例如vendors~app

总结分析

对于默认配置,首先chunks为async,说明只会对异步包进行拆分,且拆分规则必须满足cacheGroups这些前面的这些属性,那么vendors呢?也就是说只有异步包里引用的来自 node_modules的部分(例如a.js中引入的vue)才会打包到vendors中。这样如果main.js里面有引入vue的话,肯定就被重复打包到app.js了,所以会有重复打包的情况,在开发环境中,将chunks设置成all,是一个比较好的优化方式。