webpack中splitChunks分包策略的实现 |
一、为什么需要拆包随着应用程序规模的增长,JavaScript 文件的大小也越来越大 。一个大的 JavaScript 文件会导致页面加载时间过长,影响用户体验 。良好的拆包策略可以将一个大的 JavaScript 文件分割成多个较小的代码块,将公用的代码抽离成单独的 chunk,在需要的时候按需加载,并充分利用浏览器的缓存机制,如果使用合理,会极大影响加载时间 。 二、拆包方式入口起点(entry ) 代码分离(Code Splitting) 打包分离(Bundle Splitting) 综上所述,合理的拆包策略可以显著提升应用程序的性能 。代码分离通过将代码按需加载,减小初始下载量;而打包分离将应用程序拆分成多个块,实现增量更新,减少不必要的下载 。根据具体场景和需求,选择合适的拆包方式可以最大程度地优化应用程序的加载性能 。 三、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
四、splitChunks 拆包策略split-by-experience: 根据经验制定的拆分策略,自动将一些常用的 npm 包拆分为体积适中的 chunk 。适用于大多数项目 。 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分包策略内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持! |