Webpack 4 SplitChunksPlugin 配置详解与实战

作者:脚本小铺

时间:2026-10-22

浏览:568

本文详解 Webpack 4 中 SplitChunksPlugin 的配置与工作原理。涵盖默认分割条件、chunks 参数(initial/async/all)的区别,以及利用 cacheGroups 自定义缓存组、提取第三方库和禁用默认组的具体操作。通过实例演示如何优化打包体积与加载性能。

文章目录

Webpack 4 代码分割概述

提及前端构建工具,Webpack 无疑是首选。尽管前端技术迭代迅速,Parcel 和 Rollup 等工具不断涌现,但各类构建工具在竞争中相互借鉴优势,共同推动了前端工程化的发展。

Webpack 4 引入了零配置特性,并对模块打包进行了优化。原有的 CommonsChunkPlugin 已被移除,转而采用 optimization.splitChunks 进行代码分割配置。

接下来将详细介绍 SplitChunks 的具体内容。

默认分割条件与行为

默认配置行为

在默认设置下,Webpack 会依据以下条件自动执行代码分割:

  • 新生成的代码块被多个模块共享引用,或者这些模块源自 node_modules 目录。
  • 新代码块的体积在压缩前大于 30KB(未进行 min 和 gzip 处理)。
  • 对于按需加载的代码块,其并行请求的最大数量需小于或等于 5。
  • 对于初始加载的代码块,其并行请求的最大数量需小于或等于 3。

默认情况下,代码分割仅作用于按需加载的模块。若对初始块也进行优化,会增加 HTML 中 script 标签的数量,从而提升请求数。

通过以下示例可帮助理解默认配置下的打包行为。

模块全部采用同步引入


// indexA.js
import React from 'react'
import ReactDOM from 'react-dom'
import _ from 'lodash'

console.log(_.join(['a', 'b'], '~'))

ReactDOM.render(
 <div>SplitChunk</div>,
 document.getElementById('root')
)

Webpack 4 代码分割概述

由于默认配置仅影响按需加载模块,因此所有同步引入的内容均被打包在一起。

包含动态导入的模块

此处使用符合 ECMAScript 提案的 import() 语法进行动态导入。


// indexA.js
import React from 'react'
import ReactDOM from 'react-dom'
import _ from 'lodash'
import(/* webpackChunkName: "async-jquery" */ 'jquery').then(component => {
 console.log(component)
})

console.log(_.join(['a', 'b'], '~'))

ReactDOM.render(
 <div>SplitChunk</div>,
 document.getElementById('root')
)

Webpack 4 代码分割概述

当 jquery 采用动态导入时,打包结果中 jquery 会被单独打包成一个文件。

React 按需加载示例

同样地,我们尝试对 react 进行按需加载,利用 react-router 提供的方案实现。

AsyncModule 模块按照上述方案异步加载 Dashboard 组件。


import React from 'react'
import ReactDOM from 'react-dom'
import {BrowserRouter, Route} from 'react-router-dom'
import AsyncModule from './AsyncModule.jsx'
import _ from 'lodash'
import $ from 'jquery'

console.log(_.join(['a', 'b'], '~'))

ReactDOM.render(
 <div>
 <BrowserRouter>
  <Route path='/' component={AsyncModule} />
 </BrowserRouter>
 </div>,
 document.getElementById('root')
)

Webpack 4 代码分割概述

从打包结果可见,按需加载的模块被打包至 0.js 文件中。

了解了 Webpack 默认情况下的打包优化后,接下来探讨 splitChunks 的配置项。

SplitChunks 配置参数详解

配置参数说明

相关配置项如下:


module.exports = {
 //...
 optimization: {
 splitChunks: {
  chunks: 'async', 
  minSize: 30000,
  minChunks: 1,
  maxAsyncRequests: 5,
  maxInitialRequests: 3,
  automaticNameDelimiter: '~', 
  name: true,
  cacheGroups: {}
 }
 }
}
  • chunks:指定需要优化的代码块类型,可选值为 initial(初始块)、async(按需加载块)和 all(全部块),默认为 async。
  • minSize:压缩前的最小模块体积阈值,默认为 30000 字节。
  • minChunks:模块被引用的最小次数,默认为 1。
  • maxAsyncRequests:按需加载时允许的最大并行请求数,默认为 5。
  • maxInitialRequests:单个入口允许的最大并行请求数,默认为 3。
  • automaticNameDelimiter:生成块名时使用的连接符。
  • name:拆分后块的名称,默认由块名和 hash 值自动生成。
  • cacheGroups:缓存组。除上述属性外,缓存组还包含 test、priority 和 reuseExistingChunk 属性。
    • test:用于匹配哪些模块应被该缓存组处理。
    • priority:缓存组打包的优先级顺序。
    • reuseExistingChunk:若当前代码块已包含所需模块,则不生成新代码块。

上述为基本配置项,重点在于 chunks 和 cacheGroups 的配置。

chunks 参数:initial 与 all 的区别

chunks 参数详解

chunks 可选值为 initial、async 和 all。默认值为 async,前文已介绍其表现,此处分析其他两个值的效果。

当设置为 initial 或 all 时,所有来自 node_modules 的模块会被分配至名为 vendors 的缓存组;所有被引用至少两次的代码会被分配至 default 缓存组。


// indexA.js
import './Dashboard.jsx'

// indexB.js
import './Dashboard.jsx'

// Dashboard.jsx
import React from 'react'

// webpack.config.js
splitChunks: {
 chunks: 'initial'
}

Webpack 4 代码分割概述

打包结果符合预期,生成了 vendors 和 default 两个代码块。

可通过配置 optimization.splitChunks.cacheGroups.default: false 来禁用 default 缓存组。


// webpack.config.js
splitChunks: {
 chunks: 'initial',
 cacheGroups: {
 default: false
 }
}

Webpack 4 代码分割概述

关于 all 和 initial 的区别,可参考文章《Webpack 4 — Mysterious SplitChunks Plugin》(需科学上网)。

文中指出,initial 模式会分别优化异步和非异步模块,而 all 模式则对两者同时进行优化。例如,若 moduleA 在 indexA 中异步引入,在 indexB 中同步引入,在 initial 模式下 moduleA 会出现在两个打包块中,而在 all 模式下仅出现一个。

cacheGroups 自定义缓存组

cacheGroups 缓存组配置

使用 cacheGroups 可自定义打包块的行为。


// indexA.js
import React from 'react'
import ReactDOM from 'react-dom'
import _ from 'lodash'
import $ from 'jquery'

// indexB.js
import React from 'react'
import ReactDOM from 'react-dom'
import('lodash')
import $ from 'jquery'

// webpack.config.js
optimization: {
 splitChunks: {
  cacheGroups: {
  commons: {
   name: 'commons',
   chunks: 'initial',
   minChunks: 2
  }
  }
 }
 }

Webpack 4 代码分割概述

根据前文介绍的 Webpack 分割条件,部分公共模块被打包进 commons。自定义打包块的优先级默认为 0,因此公共模块会被打包进 commons,而非前文提到的默认打包块 vendors(其优先级为负值)。

为何 lodash 未被打包在一起?回顾 initial 和 all 的区别,接下来实验 all 的效果。


// indexA, indexB同上
// webpack.config.js
optimization: {
 splitChunks: {
  cacheGroups: {
   commons: {
    name: 'commons',
    chunks: 'all',
    minChunks: 2
   }
  }
 }
}

Webpack 4 代码分割概述

结果符合预期,lodash 被成功打包在一起。

提取第三方库与 Runtime 配置

提取第三方库

最后回顾 CommonsChunkPlugin 常用的分离第三方库功能。思考如何实现这一操作。

前文提到设置 chunks: initial || all 即可提取第三方库,但这会提取所有第三方库。若仅需提取 react 和 react-dom,需自定义 cacheGroup。


// indexA.js
import React from 'react'
import ReactDOM from 'react-dom'
import _ from 'lodash'
import $ from 'jquery'

// webpack.config.js
entry: {
 indexA: path.join(__dirname, 'src/indexA.js')
},
optimization: {
 splitChunks: {
  chunks: 'all',
  cacheGroups: {
   vendors: {
    test: /react/,
    name: 'vendors'
   }
  }
 }
}

Webpack 4 代码分割概述

通过重写 vendors 打包块,仅打包匹配 react 的模块,从而实现了此前 CommonsChunkPlugin 的功能。

或者采用以下方式:


// index.jsx
import React from 'react'
import ReactDOM from 'react-dom'

// webpack.config.js
entry: {
 indexA: path.join(__dirname, 'src/indexA.js'),
 vendor: ["react", "react-dom"]
},
optimization: {
 splitChunks: {
  cacheGroups: {
   vendor: {
    name: "vendor",
    chunks: "initial"
   }
  }
 }
}

Webpack 4 代码分割概述

optimization.runtimeChunk 配置

最后提及 runtimeChunk,通过 optimization.runtimeChunk: true 选项,Webpack 会在每个入口添加一个仅包含运行时(runtime)的额外代码块。(注:需根据场景使用,这会导致每个入口加载一份额外的运行时代码。)

总结

Webpack 4 的 SplitChunks 功能强大,但建议优先使用默认模式,或仅针对第三方库进行提取优化。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。

实用工具推荐

电子包浆

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

使用 ›
图片压缩

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

使用 ›
相关文章