splitChunks怎么分割降低包大小

发布时间:2022-09-20 15:38:53 作者:iii
来源:亿速云 阅读:269

本篇内容主要讲解“splitChunks怎么分割降低包大小”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“splitChunks怎么分割降低包大小”吧!

问题测验

讲解开始之前,大家先看一个问题。如果你已经知道问题的答案,而且明白为什么,就不必往下阅读了。如果不知道答案或者知道答案,但不知道原因。那么,强烈建议阅读本文。

// webpack.config.js
const path = require("path");
const HtmlWebpackPlugin = require("html-webpack-plugin");
module.exports = {
  entry: { app: "./src/index.js" },
  output: {
    filename: "[name].js",
    path: path.resolve(__dirname, "dist")
  },
  optimization: {
    splitChunks: {
      chunks: "all"
    }
  },
  plugins: [
    new HtmlWebpackPlugin()
  ]
};
// index.js
import "vue"
import(/*webpackChunkName: 'a' */ "./a");
import(/*webpackChunkName: 'b' */ "./b");
// a.js
import "vue-router";
import "./someModule"; // 模块大小大于30kb
// b.js
import "vuex";
import "./someModule"; // 模块大小大于30kb
// someModule.js
// 该模块大小超过30kb
// ...

代码分割的三种方式

webpack 中以下三种常见的代码分割方式:

entry: { app: "./index.js", app1: "./index1.js" }

第二种方式,就是在代码中自动将使用 import() 加载的模块分离成独立的包:

//...
import("./a");
//...

第三种方式,是使用 splitChunks 插件,配置分离规则,然后 webpack 自动将满足规则的 chunk 分离。一切都是自动完成的。

前两种拆分方式,很容易理解。本文主要针对第三种方式进行讨论。

splitChunks 代码拆分

splitChunks 默认配置

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

以上配置,概括如下4个条件:

// index.js
import("./a");
// ...
// a.js
import "vue";
// ...

以上代码,在默认配置下的构建结果如下:

splitChunks怎么分割降低包大小

原因分析

理解 chunks

chunks 用以告诉 splitChunks 的作用对象,其可选值有 asyncinitialall。默认值是 async,也就是默认只选取异步加载的chunk进行代码拆分。这个我们在开头的例子里已经验证。这里我们通过两个例子来看一下当chunks的值为 initialall 时,打包结果如何。 首先将chunks值改为 initial

chunks: "initial"

构建结果如下:

splitChunks怎么分割降低包大小

原因分析:

chunks 值为 initial 时,splitChunks 的作用范围变成了非异步加载的初始 chunk,例如我们的 index.js 就是初始化的时候就存在的chunk。而 vue 模块是在异步加载的chunk a.js 中引入的,所以并不会被分离出来。

chunks 仍使用 initial, 我们对 index.jsa.js 稍作修改:

// index.js
import 'vue'
import('./a')
// a.js
console.log('a')

构建结果如下:

splitChunks怎么分割降低包大小

原因分析:

vueindex.js 直接被引入,而 index.js 是初始chunk,所以分离出来打到了 vendors~app.js 中。

能不能让 splitChunks 既处理初始chunk也处理异步chunk呢?答案是可以,只需要将 chunks 改为 all

chunks: "all"

index.jsa.js 稍作修改:

// index.js
import 'vue-router'
import('./a')
// a.js
import 'vue'
console.log('a')

构建结果如下:

splitChunks怎么分割降低包大小

原因分析:

chunks 值为 all 时,splitChunks 的处理范围包括了初始chunk和异步chunk两种场景,因此 index.js 中的 vue-router 被分拆到了 vendors~app.js 中,而异步加载的chunk a.js 中的 vue 被分拆到了 3.js 中。推荐在开发中将 chunks 设置为 all

理解 maxInitialRequests

maxIntialRequests 表示 splitChunks 在拆分chunk后,页面中需要请求的初始chunk数量不超过指定的值。所谓初始chunk,指的是页面渲染时,一开始就需要下载的js,区别于在页面加载完成后,通过异步加载的js。

splitChunks 做以下修改,其他使用默认配置:

chunks: 'initial',
maxInitialRequests: 1

对 index.js 稍作修改:

// index.js
import 'vue'

构建结果如下:

splitChunks怎么分割降低包大小

原因分析:

因为 maxInitialRequests 为1,如果 vueindex.js 中拆出的话,新创建的chunk作为初始chunk index.js 的前置依赖,是需要在页面初始化的时候就先请求的。那么初始化时的请求数变成了2,因此不满足拆分条件,所以 splitChunks 没有对 index.js 进行拆分。

理解 maxAsyncRequests

maxInitialRequests 相对,maxAsyncRequests 表示 splitChunks 在拆分chunk后,并行加载的异步 chunk 数不超过指定的值。

splitChunks 做以下修改,其他使用默认配置:

maxAsyncRequests: 1

index.js 稍作修改:

// index.js
import('./a')
// a.js
import 'vue'
console.log('a')

构建结果如下:

splitChunks怎么分割降低包大小

原因分析: 因为 maxAsyncRequests 为1,由于 a.js 是通过 import() 异步加载的,此时并行的异步请求数是1。如果将 vuea.js 中拆出的话,拆出的包也将成为一个异步请求chunk。这样的话,当异步请求 a.js 的时候,并行请求数有2个。因此,不满足拆分条件,所以 splitChunks 没有对 a.js 进行拆分。

理解 minChunks

minChunks 表示一个模块至少应被指定个数的 chunk 所共享才能分割。默认为1。

splitChunks 做以下修改,其他使用默认配置:

chunks: 'all',
minChunks: 2

index.js 稍作修改:

// index.js
import 'vue'

构建结果如下:

splitChunks怎么分割降低包大小

原因分析:

因为 minChunks 为 2,所以只有当 vue 至少被2个 chunk 所共享时,才会被拆分出来。

思考题

请问如下代码,构建结果是什么?

chunks: 'all',
minChunks: 2
// index.js
import 'vue'
import './a'
// a.js
import 'vue'
console.log('a')

理解 cache groups

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

通过 cacheGroups,我们可以定义自定义 chunk 组,通过 test 条件对模块进行过滤,符合条件的模块分配到相同的组。

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

前面的例子中,你可能注意到了怎么有的拆分出的chunk名字这么奇怪,例如 vendors~app(默认由 cacheGroups 中组的 key + 源chunk名组成)。我们看一下如何自定义拆分出的chunk名。

首先找到该chunk所属的分组,该例为 vendors 分组,作如下修改,其他使用默认配置:

chunks:'all',
cacheGroups: {
    vendors: {
      test: /[\\/]node_modules[\\/]/,
      name: "customName",
      priority: -10
    }
}

对 index.js 稍作修改:

// index.js
import 'vue'

构建结果如下:

splitChunks怎么分割降低包大小

原因分析:

vue 来自 node_modules 目录,被分配到了默认的 vendors 组中,如果不指定 name 的话,会使用默认的chunk名,这里我们指定了 name,因此最终的chunk名为customName

模块还可以分配到多个不同的组,但最终会根据 priority 优先级决定打包到哪个 chunk。

新增一个分组:

chunks:'all',
cacheGroups: {
    vendors: {
      test: /[\\/]node_modules[\\/]/,
      name: "customName",
      priority: -10
    },
    customGroup: {
      test: /[\\/]node_modules[\\/]/,
      name: "customName1",
      priority: 0
    }
}

构建结果:

splitChunks怎么分割降低包大小

原因分析:

虽然 vendorscustomGroup 这个两个组的条件都符合,但由于后者的优先级更高,所以最终将 vue 打包到了 customName1.js 中。

到此,相信大家对“splitChunks怎么分割降低包大小”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

推荐阅读:
  1. 浅析:Unity3D开发的游戏如何降低包体大小
  2. 降低高水位线

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

splitchunks

上一篇:vue3 keepalive线上问题怎么解决

下一篇:web前端怎么取消请求及取消重复请求

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》