理解webpack4.splitChunks
一、前言
之前一直也没有研究过webpack4是基于怎样的规则去拆分模块的,现在正好有时间打算好好了解一下,看了官方文档也陆陆续续的看了看网上别人写的文章,感觉大部分都是将官方文档翻译了一遍,很多问题都没有解释清楚,无奈只好自己写demo去通过实际编译结果来理解,经过一天多的不断调试和百度,基本弄清楚了splitchuns的运行规则了,特此记录下来。
二、webpack中的三个概念module、chunk和bundle
在研究splitchunks之前,我们必须先弄明白这三个名词是什么意思,主要是chunk的含义,要不然你就不知道splitchunks是在什么的基础上进行拆分。
从官网上貌似没找太多的解释,去网上搜了搜基本上都在转述这位老哥的回答,我根据自己的理解给出我个人的看法:
- module:就是js的模块化webpack支持commonjs、es6等模块化规范,简单来说就是你通过import语句引入的代码。
- chunk: chunk是webpack根据功能拆分出来的,包含三种情况:
1、你的项目入口(entry)
2、通过import()动态引入的代码
3、通过splitchunks拆分出来的代码
chunk包含着module,可能是一对多也可能是一对一。
- bundle:bundle是webpack打包之后的各个文件,一般就是和chunk是一对一的关系,bundle就是对chunk进行编译压缩打包等处理之后的产出。
三、splitchunks
下面进入正题讲解splitchunks,splitchunks就算你什么配置都不做它也是生效的,源于webpack有一个默认配置,这也符合webpack4的开箱即用的特性,它的默认配置如下:
module.exports = { //... optimization: { splitchunks: { chunks: 'async', minsize: 30000, minchunks: 1, maxasyncrequests: 5, maxinitialrequests: 3, automaticnamedelimiter: '~', name: true, cachegroups: { vendors: { test: /[\\/]node_modules[\\/]/, priority: -10 }, default: { minchunks: 2, priority: -20, reuseexistingchunk: true } } } } };
我们现在用一个简单的react项目来测试下打包之后的效果如何,我的这个项目有两个页面entry1.js和page1.js,entry1.js是入口文件,entry1.js里面动态引入了page1.js。
entry1.js
1 import react from 'react' 2 import reactdom from 'react-dom' 4 5 const app = () => { 6 let page1 = null 7 8 import(/* webpackchunkname: "page1" */'./routes/page1').then(comp => { 9 page1 = comp 10 }) 11 console.log($) 12 return ( 13 <div> 14 <div>app</div> 15 <page1 /> 16 </div> 17 ) 18 } 19 20 reactdom.render(<app />, document.getelementbyid('root'))
page1.js
1 import react from 'react' 2 import _ from 'lodash' 4 5 const page1 = () => { 6 console.log($) 7 8 return ( 9 <div> 10 <div>page1</div> 11 </div> 12 ) 13 } 14 15 export default page1
让我们想一想打包之后的代码是怎样的呢?
以上就是打包之后的代码,是否如你所想呢,让我们分析一下:
1、第一个main文件就是打包之后的入口文件,这个我们上面说了webpack会把入口文件单独拆成一个chunk,这个没有问题
2、第三个page1文件,我们上面也说过动态加载得文件webpack会将其拆分为一个chunk,这个也没有问题
3、第二个vendor~page1文件,这个是对page1文件里面引入的第三方库进行打吧,具体就是lodash那个第三方库了,这个涉及到cachegroup,我们在下面的系列文章里面会详细讲述
以上就是所有被拆分出来的包,但是我们发现有一个文件没有拆分出来,那就是entry1里面引入的第三方库react-dom,这个是为什么呢,这个就要涉及到我们接下来讲到的chunks属性的配置。
注意:这里提个小问题为什么react-dom这个第三方库只在entry1.js里面引入了一次就被拆分出来了?这个答案我将在第三篇文章《理解webpack4.splitchunks之cachegroups》里面进行解释。
为了方便阅读我将整个系列分为了若干小部分,大家可以各区所需:
《理解webpack.splitchunks之chunks》
《理解webpack.splitchunks之cachegroups》
《理解webpack.splitchunks之maxinitialrequests》
《理解webpack.splitchunks之maxasyncrequests》
文章中所用到的源码仓库地址是webpack_splitchunks_demo