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分包策略内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • php利用curl获取远程图片实现方法

    php利用curl获取远程图片实现方法

    这篇文章主要介绍了php利用curl获取远程图片实现方法,curl要求php环境支持,需要的朋友可以参考下
    2015-10-10
  • js字符串截取指定字符前面/后面的字符串代码

    js字符串截取指定字符前面/后面的字符串代码

    在页面数据处理的过程中都会不可避免的使用字符串的截取操作,下面这篇文章主要给大家介绍了关于js字符串截取指定字符前面/后面的字符串,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-06-06
  • JS简单去除数组中重复项的方法

    JS简单去除数组中重复项的方法

    这篇文章主要介绍了JS简单去除数组中重复项的方法,涉及javascript针对数组的遍历、判断与运算相关操作技巧,需要的朋友可以参考下
    2016-09-09
  • 理解javascript中的with关键字

    理解javascript中的with关键字

    这篇文章主要帮助大家理解javascript中的with关键字,学习with关键字的作用,感兴趣的小伙伴们可以参考一下
    2016-02-02
  • postman+json+springmvc测试批量添加实例

    postman+json+springmvc测试批量添加实例

    下面小编就为大家分享一篇postman+json+springmvc测试批量添加实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-03-03
  • JavaScript等比例缩放图片控制超出范围的图片

    JavaScript等比例缩放图片控制超出范围的图片

    当网页加载一个尺寸比较大的图片时,往往会把一个网页撑的变形,页面变得很难看,于是我们就想到了用JS去控制超出一定范围的图片
    2013-08-08
  • js观察者模式的弹幕案例

    js观察者模式的弹幕案例

    这篇文章主要为大家详细介绍了js观察者模式的弹幕案例,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-11-11
  • JavaScript 格式字符串的应用

    JavaScript 格式字符串的应用

    在使用JavaScript中的Date对象时,有一个常用的操作就是输出。但Date对象自带的toString()方法输出的格式并不能满足用户多样化的需求。我在想,是不是可以将C#中DateTime.ToString(string format)方法的形式引入到JavaScript中呢?
    2010-03-03
  • jQuery随便控制任意div隐藏的方法

    jQuery随便控制任意div隐藏的方法

    这篇文章介绍了jQuery随便控制任意div隐藏的方法,有需要的朋友可以参考一下
    2013-06-06
  • JavaScript时间复杂度和空间复杂度

    JavaScript时间复杂度和空间复杂度

    这篇文章主要介绍了JavaScript时间复杂度和空间复杂度,时间复杂度和空间复杂度是衡量一个算法是否优秀的标准,通常我们比较两个算法时会用预先估算和事后统计,下文详细介绍,需要的朋友可以参考一下
    2022-07-07

最新评论