脚本之家

电脑版
提示:原网页已由神马搜索转码, 内容由www.jb51.net提供.
您的位置:首页网络编程JavaScriptjavascript技巧→ webpack splitChunks分包策略

webpack中splitChunks分包策略的实现

  更新时间:2024年06月28日 09:05:20  作者:Lsx_codeShare 
splitChunks是 webpack 中用于分包的配置选项之一,本文主要介绍了webpack中splitChunks分包策略的实现,具有一定的参考价值,感兴趣的可以了解一下

一、为什么需要拆包

随着应用程序规模的增长,JavaScript 文件的大小也越来越大。一个大的 JavaScript 文件会导致页面加载时间过长,影响用户体验。良好的拆包策略可以将一个大的 JavaScript 文件分割成多个较小的代码块,将公用的代码抽离成单独的 chunk,在需要的时候按需加载,并充分利用浏览器的缓存机制,如果使用合理,会极大影响加载时间。

二、拆包方式

入口起点(entry )
通过使用入口起点的方式,可以将代码分离成多个单独的文件,这些文件可以通过 webpack 配置一个数组结构的 entry 选项指定。并且在其中传入不同类型的文件,可以实现将 CSS 和 JavaScript(和其他)文件分离在不同的 bundle。但是,这种方式有一些缺点,如无法动态加载,无法共享模块等。

代码分离(Code Splitting)
代码分离指将代码分成不同的包/块,然后可以按需加载,而不是加载包含所有内容的单个包。用户只需要下载当前他正在浏览站点的这部分代码,代码分离可以使用ES6模块中的 import() 函数动态的加载模块。使用动态导入的模块会被分割到一个单独的 chunk 中。

打包分离(Bundle Splitting)
webpack 为单个应用程序生成多个 bundle 文件。如果你有一个体积巨大的文件,并且只改了一行代码,用户仍然需要重新下载整个文件。但是如果你把它分为了两个文件,那么用户只需要下载那个被修改的文件,而另一个文件浏览器可以从缓存中加载,从而减少重新发布并由此被客户端重新下载的代码量。

综上所述,合理的拆包策略可以显著提升应用程序的性能。代码分离通过将代码按需加载,减小初始下载量;而打包分离将应用程序拆分成多个块,实现增量更新,减少不必要的下载。根据具体场景和需求,选择合适的拆包方式可以最大程度地优化应用程序的加载性能。

三、splitChunks介绍

splitChunks 将满足拆分规则的构建内容抽出来单独打包,从而达到抽离公共模块,减少重复打包的目的。splitChunks 中的配置项用来确定具体的拆分规则,其中的 cacheGroups 配置项必须同时满足其下的所有条件才能生效。

webpack5 中 splictChunks 的默认配置为:

module.exports = {
optimization: {
splitChunks: {
chunks: 'async',
// 生成的 chunk 的最小体积,单位为字节(bytes)。内容超过了minSize的值,才会进行打包
minSize: 20000,
minRemainingSize: 0,
// 在拆分之前,必须共享的模块的最小 chunk 数。
minChunks: 1,
// 在按需加载时,允许的最大并行请求数。
maxAsyncRequests: 30,
// 入口点允许的最大并行请求数。
maxInitialRequests: 30,
// 超过这个值就会进行强制分包处理,无视minRemainingSize,maxAsyncRequests,maxInitialRequests
enforceSizeThreshold: 50000,
cacheGroups: {
vendors: {
test: /[\\/]node_modules[\\/]/,
priority: -10,
// 如果当前 chunk 包含已从主 bundle 中拆分出的模块,则它将被重用,而不是生成新的模块
reuseExistingChunk: true,
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true,
},
},
},
},
};

其中chunks属性可配置值有 all、 async 、 initial ,默认值是 async

  • async : 异步加载进来的包才会校验分包规则,进行分包抽离。如果动态加载的包也同时引用了其它包且命中分包规则也会被抽离出来。
  • initial : 表示只从入口模块进行拆分。
  • all : 表示入口模块和异步加载的模块都要进行拆分。

四、splitChunks 拆包策略

split-by-experience: 根据经验制定的拆分策略,自动将一些常用的 npm 包拆分为体积适中的 chunk。适用于大多数项目。
如下示例,react、antd 会被包拆分到了单独的chunk,其余三方包会在vendorjs。其余的包也可以配置缓存组。如果拆分力度比较细的话还是需要写上一些缓存组的。

splitChunks: {
// chunks、minSize、minChunks 将对所有缓存组生效
chunks: 'all', // 对所有的chunk进行拆分
minSize: 20000, // 拆分 chunk 的最小体积 20000 bytes
minChunks: 2, // 需在两个模块中共享才进行拆分
cacheGroups: {
vendor: {
name: 'vendor', // chunk 的名称 vendor
test: /[\\/]node_modules[\\/]/i, // 匹配node_modules下所有的chunk
priority: 10, // 优先级10 优先将node_modules下的chunk拆分到vendor组
reuseExistingChunk: true, // 重用模块,而不是重新生成
enforce: true, // 强制拆分
},
default: { // 默认组 非node_modules下的文件块 将执行default缓存组规则
reuseExistingChunk: true,
priority: -10, // 优先级 -10
enforce: true, // 强制拆分
},
react: { // react组
name: 'react',
test: /[\\/]node_modules[\\/]react[\\/]/, // 匹配node_modules下的react库
priority: 20, // 优先级20 优先将node_modules下的react拆分出去
minChunks: 2,
reuseExistingChunk: true,
},
antd: { // antd组
name: 'antd',
test: /[\\/]node_modules[\\/]antd[\\/]/, // 匹配node_modules下的antd库
priority: 20, // 优先级20 优先将node_modules下的antd拆分出去
minChunks: 2,
reuseExistingChunk: true, // 重用模块,而不是重新生成
},
}
}

split-by-module: 按 NPM 包的粒度拆分,每个 NPM 包对应一个 chunk。

假如应用程序添加或升级了某个 npm 包,那么 vendor.js 的哈希值将会发生改变,这意味着用户在访问页面时需要重新下载 vendor.js文件。这个时候如果对antd进行了升级或新增/删除了一个antd组件,那么用户不需要重新下载vendor.js文件,而只需要下载antd模块对应的chunk。因为每个chunk都有一个独立的哈希值,当我们对单独的chunk进行修改时,只会影响到对应的chunk文件,而不会影响其他chunk文件。这样就实现了对npm包的增量更新。

这种情况下如果npm包比较多的情况下,会产生高并发请求。对于支持http2的浏览器是没有问题的。但是浏览器并不支持http2的话,也就是http1.1会存在对头阻塞的问题。不过http2兼容性挺好的

splitChunks: {
chunks: 'all',
enforceSizeThreshold: 50000,
cacheGroups: {
vendors: {
priority: -10,
test: /[\\/]node_modules[\\/]/,
name(module2) {
return module2.context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/)?.[1];
},
},
},
minSize: 0,
maxInitialRequests: Infinity,
},

single-vendor: 将所有 NPM 包的代码打包到一个单独的 chunk 中。

这种情况的话,只要三方包有改动,文件hash就会改变。如果频繁改动npm包的话,浏览器缓存效率相对较低

vendor: {
name: 'vendor', // chunk 的名称 vendor
test: /[\\/]node_modules[\\/]/i, // 匹配node_modules下所有的chunk
priority: 10, // 优先级10 优先将node_modules下的chunk拆分到vendor组
reuseExistingChunk: true, // 重用模块,而不是重新生成
enforce: true, // 强制拆分
},

split-by-size:根据模块大小自动进行拆分。

符合大小范围内的包就会被拆出来

splitChunks: {
chunks: 'all',
minSize: 20000, // 20 KB
maxSize: 50000, // 50 KB
cacheGroups: {
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true,
},
},
},

五、总结

要根据业务场景来选择合适的分包策略,拆到什么力度、什么程度需要自己斟酌。要注意拆包之后相同的模块不要被重复打包。

到此这篇关于webpack中splitChunks分包策略的实现的文章就介绍到这了,更多相关webpack splitChunks分包策略内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

    • 这篇文章主要为大家详细分享了laypage分页控件使用实例,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
      2016-05-05
    • 这篇文章主要介绍了ES6中的迭代器、Generator函数以及Generator函数的异步操作方法,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
      2019-05-05
    • 这篇文章主要为大家详细介绍了javascript表单正则应用,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
      2017-02-02
    • 设置div的值想必大家都会吧,按要说动态设置想必知道的人及寥寥无几了,下面有个不错的示例,希望对大家有所帮助
      2013-10-10
    • 这篇文章主要介绍了Javascript闭包的概念及用法,以实例形式深入浅出的分析了闭包的功能及使用时的注意事项,非常具有实用价值,需要的朋友可以参考下
      2015-01-01
    • 这篇文章主要介绍了JavaScript中Array实例方法map的实现方法,map() 方法创建一个新数组,其结果是原数组中的每个元素都调用一个提供的函数后返回的结果,文中有详细的代码示例供大家参考,需要的朋友可以参考下
      2024-03-03
    • 本篇文章主要是对动态添加删除表格行的js实现代码进行了介绍,需要的朋友可以过来参考下,希望对大家有所帮助
      2014-02-02
    • 这篇文章主要给大家介绍了关于JS中相等性判断===、 ==和Object.is()的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用JS具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
      2019-11-11
    • 在社交小程序里有个常见的场景是关注功能,我们本篇以关注已经发布的文章为例,讲解一下关注功能如何实现
      2022-08-08
    • 在这一章我会讲解给元素注册事件的最好的一种办法,那就是:确保一个特定的事件在特定的HTML元素上发生并且能运行特定的脚本。
      2010-02-02

    最新评论