一般状况下咱们的 WebApp 是有咱们的自身代码和第三方库组成的,咱们自身的代码是会经常变更的,而第三方库除非有较大的版本升级,否则是不会变的,因此第三方库和咱们的代码须要分开打包,咱们能够给第三方库设置一个较长的强缓存时间,这样就不会频繁请求第三方库的代码了。javascript
那么如何提取第三方库呢?在 webpack4.x 中, SplitChunksPlugin 插件取代了 CommonsChunkPlugin 插件来进行公共模块抽取,咱们能够对SplitChunksPlugin 进行配置进行 拆包 操做。html
SplitChunksPlugin配置示意以下:前端
optimization: {
splitChunks: { chunks: "initial", // 代码块类型 必须三选一: "initial"(初始化) | "all"(默认就是all) | "async"(动态加载) minSize: 0, // 最小尺寸,默认0 minChunks: 1, // 最小 chunk ,默认1 maxAsyncRequests: 1, // 最大异步请求数, 默认1 maxInitialRequests: 1, // 最大初始化请求书,默认1 name: () => {}, // 名称,此选项课接收 function cacheGroups: { // 缓存组会继承splitChunks的配置,可是test、priorty和reuseExistingChunk只能用于配置缓存组。 priority: "0", // 缓存组优先级,即权重 false | object | vendor: { // key 为entry中定义的 入口名称 chunks: "initial", // 必须三选一: "initial"(初始化) | "all" | "async"(默认就是异步) test: /react|lodash/, // 正则规则验证,若是符合就提取 chunk name: "vendor", // 要缓存的 分隔出来的 chunk 名称 minSize: 0, minChunks: 1, enforce: true, reuseExistingChunk: true // 可设置是否重用已用chunk 再也不建立新的chunk } } } } 复制代码
SplitChunksPlugin 的配置项不少,能够先去官网了解如何配置,咱们如今只简单列举了一下配置元素。vue
若是咱们想抽取第三方库能够这样简单配置java
splitChunks: {
chunks: 'all', // initial、async和all minSize: 30000, // 造成一个新代码块最小的体积 maxAsyncRequests: 5, // 按需加载时候最大的并行请求数 maxInitialRequests: 3, // 最大初始化请求数 automaticNameDelimiter: '~', // 打包分割符 name: true, cacheGroups: { vendor: { name: "vendor", test: /[\\/]node_modules[\\/]/, //打包第三方库 chunks: "all", priority: 10 // 优先级 }, common: { // 打包其他的的公共代码 minChunks: 2, // 引入两次及以上被打包 name: 'common', // 分离包的名字 chunks: 'all', priority: 5 }, } }, 复制代码
这样彷佛大功告成了?并无,咱们的配置有很大的问题:node
下图示意了如何将第三方库进行拆包,基础型的 react 等库与工具性的 lodash 和特定库 Echarts 进行拆分react
cacheGroups: {
reactBase: { name: 'reactBase', test: (module) => { return /react|redux/.test(module.context); }, chunks: 'initial', priority: 10, }, utilBase: { name: 'utilBase', test: (module) => { return /rxjs|lodash/.test(module.context); }, chunks: 'initial', priority: 9, }, uiBase: { name: 'chartBase', test: (module) => { return /echarts/.test(module.context); }, chunks: 'initial', priority: 8, }, commons: { name: 'common', chunks: 'initial', priority: 2, minChunks: 2, }, } 复制代码
咱们对 chunk 进行 hash 化,正以下图所示,咱们变更 chunk2 相关的代码后,其它 chunk 都没有变化,只有 chunk2 的 hash 改变了webpack
output: {
filename: mode === 'production' ? '[name].[chunkhash:8].js' : '[name].js', chunkFilename: mode === 'production' ? '[id].[chunkhash:8].chunk.js' : '[id].js', path: getPath(config.outputPath) } 复制代码
咱们经过 http 缓存+webpack hash 缓存策略使得前端项目充分利用了缓存的优点,可是 webpack 之因此须要传说中的 webpack配置工程师 是有缘由的,由于 webpack 自己是玄学,仍是以上图为例,若是你 chunk2的相关代码去除了一个依赖或者引入了新的可是已经存在工程中依赖,会怎么样呢?git
咱们正常的指望是,只有 chunk2 发生变化了,可是事实上是大量不相干的 chunk 的 hash 发生了变更,这就致使咱们缓存策略失效了,下图是变动后的 hash,咱们用红圈圈起来的都是 hash 变更的,而事实上咱们只变更了 chunk2 相关的代码,为何会这样呢?github
webpack hash缓存相关内容建议阅读此文章 做为拓展