一步一步的了解webpack4的splitChunk插件

简介:

初衷

webpack4出了两个月,发现大家包括我对splitChunk的使用都还是在摸索阶段。我也看了挺多别人的配置demo,都觉得不太满意或者没得到太好的解惑,issue 下面的问题也没什么人回复,只能自己操作了,顺便记录下来,如果大家有更好的,欢迎评论区留下地址。

常用参数

  • minSize(默认是30000):形成一个新代码块最小的体积
  • minChunks(默认是1):在分割之前,这个代码块最小应该被引用的次数(译注:保证代码块复用性,默认配置的策略是不需要多次引用也可以被分割)
  • maxInitialRequests(默认是3):一个入口最大的并行请求数
  • maxAsyncRequests(默认是5):按需加载时候最大的并行请求数。
  • chunks (默认是async) :initial、async和all
  • test: 用于控制哪些模块被这个缓存组匹配到。原封不动传递出去的话,它默认会选择所有的模块。可以传递的值类型:RegExp、String和Function
  • name(打包的chunks的名字):字符串或者函数(函数可以根据条件自定义名字)
  • priority :缓存组打包的先后优先级。

如果你对这些配置还是不熟悉的话,一拉到底,看看文档

正文

先总览一下所有配置,后续会根据demo跑一遍常见的需求。



optimization: {
  splitChunks: {
     chunks: "async", // 必须三选一: "initial" | "all"(推荐) | "async" (默认就是async)
     minSize: 30000, // 最小尺寸,30000
     minChunks: 1, // 最小 chunk ,默认1
     maxAsyncRequests: 5, // 最大异步请求数, 默认5
     maxInitialRequests : 3, // 最大初始化请求书,默认3
     automaticNameDelimiter: '~',// 打包分隔符
     name: function(){}, // 打包后的名称,此选项可接收 function
     cacheGroups:{ // 这里开始设置缓存的 chunks
         priority: 0, // 缓存组优先级
         vendor: { // key 为entry中定义的 入口名称
             chunks: "initial", // 必须三选一: "initial" | "all" | "async"(默认就是async) 
             test: /react|lodash/, // 正则规则验证,如果符合就提取 chunk
             name: "vendor", // 要缓存的 分隔出来的 chunk 名称 
             minSize: 30000,
             minChunks: 1,
             enforce: true,
             maxAsyncRequests: 5, // 最大异步请求数, 默认1
             maxInitialRequests : 3, // 最大初始化请求书,默认1
             reuseExistingChunk: true // 可设置是否重用该chunk
         }
     }
  }
 },

接下来看看第一个例子


	entry: {
		pageA: "./pageA", // 引用utility1.js  utility2.js
		pageB: "./pageB", // 引用utility2.js  utility3.js
		pageC: "./pageC"  // 引用utility2.js  utility3.js
	},
	
	optimization: {
		splitChunks: {
			cacheGroups: {
				commons: {
					chunks: "initial",
					minChunks: 2,
					maxInitialRequests: 5, // The default limit is too small to showcase the effect
					minSize: 0 // This is example is too small to create commons chunks
				}
			}
		}
	},

结果如图,一切都很正常 commons~pageA~pageB~pageC.js 文件就是utility2.js commons~pageB~pageC.js,根据上述代码,这里的utility2被引用了三次,首先就被抽离了commons~pageA~pageB~pageC.js,然后utility3被引用了两次就放到了commons~pageB~pageC.js,最后只剩下被引用一次的utility1.js,就直接放到了pageA.js里面,如果这里的utility1.js的也是两次,他还是会新建一个chunk放进去,而不是合并到commons~pageB~pageC.js,除非同入口引用才会合并。

mpageA.js pageB.js pageC.js


7b2c83c92fdea2781d5bba7fba2035388f0c9e76

这里有个地方是需要优化一下的,就是pageA.js pageB.js pageC.js的代码不多,但是打出来的包很大,肯定是一些webpack的运行文件,直接加上 runtimeChunk


    runtimeChunk: "single"
    // 等价于
    runtimeChunk: {
      name: "manifest"
    }

现在就好了

998c878582223004c6084b80a98ef812ad49e4b1

引用第三方模块 pageA引用vue.js pageB引用react react-dom



    vendor: {
		test: /node_modules/,
		chunks: "initial",
		name: "vendor",
		priority: 10,
		enforce: true
	}

但是,这样子的话,会把pageA pageB pageC所有的库都打包到一起vendor.js


6d7e28f4aa798fa5cb87864474005381f4b51e6a

假如我想拆分这个vendor.js为pageA-vendor.js pageB-vendor.js怎么办,我试了很久,试出一个最简单的办法,去掉手动的vendor,让插件自动处理。


splitChunks: {
      chunks: "all",
      cacheGroups: {
				commons: {
					chunks: "initial",
					minChunks: 2,
					maxInitialRequests: 5, // The default limit is too small to showcase the effect
					minSize: 0 // This is example is too small to create commons chunks
				}
			}
		},

c061f3851bf1928ba92f4d8dd9e9b0a7a842ee91

后来,我把webpack mode改成production后,发现不管用了,同样的配置,在生产模式下,打包出来的东西有点匪夷所思,vendor-pageB.js被合并到了pageB.js里面了。

37c9c97c643a9c2c5e3e129d004b72aacfeda848

后来我折腾了好久也分析不出来为什么,自己折腾出来一种方式,还是老子手动来吧,自动化一边去


        commons: {
          chunks: "initial",
          minChunks: 2,
          maxInitialRequests: 5, // The default limit is too small to showcase the effect
          minSize: 0 // This is example is too small to create commons chunks
	},
        'vendor-pageA': {
          test: /vue/, // 直接使用 test 来做路径匹配
          chunks: "initial",
          name: "vendor-pageA",
          enforce: true,
        },
        'vendor-pageB': {
          test: /react/, // 直接使用 test 来做路径匹配
          chunks: "initial",
          name: "vendor-pageB",
          enforce: true,
        },


成功打包出来了自己想要的东西。

520c1373ff1ba1b872125b451ce3a87e58efb233


动态引入

动态引入大家应该都不陌生,就是大家所说的懒加载,直接在pageA和pageB页面里动态引入common-async.js,在这里我先说说,splitChunk应该是可以自动化处理类似commonChunk里的async,child等情况的。


import(/* webpackChunkName: "common-async.js" */"./common-async").then(common => {
  console.log(common);
})

还不错,成功打包出来了

800cbae1f2554198826fefc74405e2a8a8c35c6d

f.js成功的被抽离出来了,其他文件也没有被重复打包,挺好的。

f8fc23c948fabe8d5b9f17106a55a6db256a1eb2

注意的地方

  • cacheGroups 会继承和覆盖splitChunks的配置项,但是test、priorty和reuseExistingChunk只能用于配置缓存组。。
  • cacheGroups 里的每一项最好都要加上chunks参数,不然可能打包不出来你想要的东西。
  • minSize 默认是30KB(注意这个体积是压缩之前的)在小于30kb的情况下一定要设置一个值,否则也可能打包不出来你想要的东西,而且这东西要加在cacheGroups里面。
  • priority 在某些情况下,还是挺有用的,可以设置打包chunks的优先级。

上面的例子里面配置了一个commons,这里的name可以自己设置,也可以不设置,我是没设置的,你可以试试设置了是什么样子的,然后你就会明白这个name其实在某些情况下还是不设置的比较好。



   commons: {
         	chunks: "initial",
		minChunks: 2,
		maxInitialRequests: 5, // The default limit is too small to showcase the effect
		minSize: 0 ,
		name:

总结

可见,splitChunk在懒加载方面,自动化处理的挺不错的,但在多页面的配置(根据不同的页面抽离不同的vendor)里,他因为有自己的一套优化策略,往往会得到不是我们想要的输出。这篇文章只是我初步的一些常识,我还没有深入去看源码,后续有空可能会补上splitChunk源码分析,到时候就更清晰了

源码

代码分割

代码懒加载

参考文章

splitChunk中文版

splitChunk英文版

webpack文档

官方demo



原文发布时间为:2018年05月26日
原文作者:乘风gg

本文来源: 掘金 如需转载请联系原作者




相关文章
|
缓存 JavaScript 前端开发
webpack4.0各个击破(4)—— Javascript & splitChunk
目录 一. Js模块化开发 二. Js文件的一般打包需求 三. 使用webpack处理js文件 3.1 使用babel转换ES6+语法 3.2 脚本合并 3.3 公共模块识别 3.4 代码分割 3.5 代码混淆压缩 四. 细说splitChunks技术 4.1 参数说明 4.2 参数配置 4.3 代码分割实例 五. 参考及附件说明 webpack作为前端最火的构建工具,是前端自动化工具链最重要的部分,使用门槛较高。
1689 0
|
1月前
|
JavaScript 前端开发
webpack成长指北第9章---webpack如何对icon字体进行打包
webpack成长指北第9章---webpack如何对icon字体进行打包
28 1
|
1月前
|
前端开发 JavaScript
webpack成长指北第7章---webpack的css\less\scss样式打包
webpack成长指北第7章---webpack的css\less\scss样式打包
41 0
|
1月前
|
前端开发 JavaScript
webpack成长指北第8章---webpack的CSS Modules打包
webpack成长指北第8章---webpack的CSS Modules打包
19 0
|
7月前
|
资源调度 前端开发 JavaScript
深入理解Webpack:现代Web开发的打包工具
Webpack是一款强大的开源JavaScript模块打包工具,它在现代Web开发中扮演着至关重要的角色。通过Webpack,开发者可以有效地管理和打包项目中的各种资源,包括JavaScript、CSS、图片等,使Web应用程序更具可维护性和性能。在本博客中,我们将深入研究Webpack的核心概念、配置、加载器、插件和最佳实践,以帮助您更好地掌握这个强大的工具。
39 0
|
7月前
|
JavaScript Shell 开发工具
webpack打包工具系列
webpack打包工具系列
31 0
|
4月前
webpack 使用打包报错 ERROR in node_modules\@types\node\ts4.8\assert.d.ts
webpack 使用打包报错 ERROR in node_modules\@types\node\ts4.8\assert.d.ts
106 0
|
4月前
|
JavaScript 数据库
使用 Webpack 打包 node 程序,node_modules 真的被干掉啦
使用 Webpack 打包 node 程序,node_modules 真的被干掉啦
68 0
|
7月前
|
JavaScript
Webpack4 创建项目以及打包一个JS文件
Webpack4 创建项目以及打包一个JS文件
68 0
|
3月前
|
前端开发 JavaScript 开发者
webpack打包机制,构建过程和配置
webpack打包机制,构建过程和配置
19 0

热门文章

最新文章