背景
如果不提取公共部分会有什么后果?
1. 相同资源重复加载引用,浪费用户流量以及服务器成本;
2. 每个页面需要加载的资源太多,导致网页首页加载缓慢;
提取之后有什么优点?
1. 相同资源只打包加载一次,减少网络传输流量,降低服务器压力;
2. 页面加载速度加快,提交用户体验;
具体用法
思路
1. 根据项目使用的技术栈,把所有页面都要使用到的基础库提取出来,形成一个`base.js`,这个文件包含技术栈运行所需要的所有基础环境依赖;(只要技术栈不变,基本可以持久缓存)
2. 剔除所有公共基础依赖代码之后,再从所有页面中把都依赖的公共代码提取出来,形成一个`common.js`;
3. 再为每个页面生成一个独立的文件,那这些文件就不再包含`base.js`、`common.js`的代码,只包含各个页面独立的业务代码;
定义与概念
CommonsChunkPlugin
用于提取公共代码,根据配置,把基础库以及业务逻辑公共代码抽离提取出来,减少资源重复引用;
CommonsChunkPlugin
对单入口文件不能提取公共的代码,只能提取webpack
runtime
的环境代码;提取的对象是
配置参数
name: ''
提取公共代码的文件名
names: string[]
names
中配置的是入口名,不是路径,如果这里配置的名字与 入口chunk(输出文件名,在entry中设置或在动态输出)中的对应起来,则直接提取,如果没有在entry中同名,则创建一个包含webpack
运行环境的环境代码,并作为抽离内容,把运行环境从提取入口中抽离出来;
chunks: string[]
chunks
配置的是提取公共代码的源,即需要在哪些入口中提取公共的代码;我的理解是这里如果自由配置的话,应该是要在入口chunk那里选择需要提取的入口(这个不知道对不对,因为我如果直接引用文件路径的话,效果没看到)
如果不设置这个值,所有入口chunk,都会作为提取的对象
filename: string
common
chunk
文件名模版,如果不设置,则不修改原来的文件名(也不会修改在name/names
中配置的名字,但是如果配置了,优先使用)
minChunks: number | Infinity | function(module, count) => boolean
number
一个模块被提取之前,必须要在 入口chunks中出现的至少次数;
Infinity
默认是对所有chunk进行提取;
function(module, count) => boolean
自定义提取的规则
minChunks
取值需大于2,小于chunks
的长度(即chunks配置项的长度或所有入口的长度)
minSize: number
在公共模块创建之前,所有 公共模块的最小大小
children: boolean
如果设置为 true
,所有 公共chunk 的子模块都会被选择;一般不设置这个值,毕竟我们值为了对公共代码的抽离,而不是想要全部抽离;不过这个也要针对不同的项目来处理,毕竟配置这个东西也是很自由的;
async:boolean|string
这个暂时没有研究出来是什么.....
具体配置
这个的配置一点也不复杂,主要是要根据实际情况进行配置比较复杂,情况一般分成下面几种
1. 项目是单入口应用还是多入口应用,这决定你是否合适使用CommonsChunkPlugin
2. 对哪些入口chunk
进行提取,这决定了 names
、chunks
、children
配置项的设置
3. 提取的粒度,这决定了minChunks
、minSize
配置项的设置
基本上根据上面几条,然后配置entry
以及plugin
就OK了,抽取的思路文章开头也提到了,所以就不列举各种情况了
// 提取公共代码主要修改的范围如下,
// manifest 的提取是把webpack启动运行部分代码,把部分代码抽离出来,
// 那每次业务代码有修改时,并不会影响到这个文件的hash,那就可以持久化在浏览器,减少用户加载的流量
module.exports = {
entry: {
main: ['./src/index.js'],
vendor: ['react']
},
plugins: [
new webpack.optimize.CommonsChunkPlugin({
names:['vendor', 'manifest'],
children: false, // 是否对所有源chunks的子模块都包含
minChunks: 2, // 提取代码的粒度
// chunks: [], // 需要提取公共代码的源chunks
}),
]
}