Webpack splitChunks 分包策略详解与实战配置

作者:白帽猫

时间:2026-11-01

浏览:647

本文深入解析 Webpack 中 splitChunks 插件的分包机制,涵盖拆包必要性、常见策略(如按经验、模块粒度、大小拆分)及默认配置详解。通过具体 cacheGroups 配置示例,展示如何优化代码加载性能、提升浏览器缓存命中率,并提供不同场景下的最佳实践建议。

文章目录

一、为何实施代码分割

随着应用规模扩大,JavaScript 文件体积随之增加。大型 JS 文件会延长页面加载时间,损害用户体验。有效的分割策略可将大文件拆分为多个小块,将公共代码提取为独立 chunk,实现按需加载并充分利用浏览器缓存,合理配置可显著优化加载速度。

二、分割方案概述

入口起点(entry) 利用入口起点可将代码分离为多个独立文件,通过 webpack 配置数组结构的 entry 选项指定。此方式可分离 CSS 与 JavaScript 等不同类型文件,但存在无法动态加载、模块无法共享等局限。

代码分离(Code Splitting) 代码分离指将代码划分为不同包/块,支持按需加载,避免加载包含所有内容的单一包。用户仅需下载当前浏览页面所需的代码,可通过 ES6 模块的 import() 函数动态加载模块。动态导入的模块将被分割至独立 chunk。

打包分离(Bundle Splitting) webpack 为单一应用生成多个 bundle 文件。若仅修改巨大文件中的一行代码,用户仍需重新下载整个文件。若将其分为两个文件,用户仅需下载被修改的文件,另一文件可从缓存加载,从而减少重新发布及客户端重新下载的代码量。

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

三、splitChunks 机制解析

splitChunks 将符合拆分规则的构建内容抽离并单独打包,旨在提取公共模块,减少重复打包。splitChunks 的配置项用于确定具体拆分规则,其中 cacheGroups 配置项必须同时满足其下所有条件方可生效。

webpack5 中 splitChunks 的默认配置如下:

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 进行升级或新增/删除组件,用户无需重新下载 vendor.js,仅需下载 antd 模块对应的 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 分包策略内容请搜索本站历史文章或继续浏览下方相关文章,希望大家今后多多支持本站!

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章