webpack提取公共js代码
- webpack打包js代码与提取公共js代码分析
- webpack提取公共js代码示例
一、分析
webpack默认打包js代码时,是将从入口js模块开始,将入口js模块所依赖的js以及模块逐层依赖的模块,全部以入口js模块为主体全部打包至生成的对应js文件中。即使是多个js入口依赖链模块依赖了同一个模块也会被重复打包至不同的js文件中,这种打包方式会产生比较大的代码冗余。
通过上图可以看到,A模块会重复出现在bundle1、bundle2、bundle3中;B模块虽然只被M3依赖,但是由于M3同时被三个入口模块依赖,所以B模块也会同时出现在最后生成的三个js文件中,到了M这一层,M3的代码肯定会重复出现最后的三个js文件中,这个依赖模型图就可以看出因为相互依赖,导致的打包时代码冗余会很大。所以,提取公共js代码是性能优化的重要方式。
关于提取公共js代码并非是被依赖了多次就一定会被提取为公共代码,暂且不讨论这个并非是什么,先思考一个问题“如果一个模块非常小,但被多个模块依赖,是否就值得提取为公共代码模块呢?”
显然,如果是一个非常小的模块被提取为公共代码是非常不合适的,相对计算机内存等硬件性能而言,网络请求对系统性能的影响更大,因为网络传输存在太多不能确定的因素,所以提取公共js代码也会有一些(参数)约束,以求在相对的系统性能下达到系统性能的最佳状态。
关于webpack4的系统优化详细文档手册可以查看这里:https://webpack.docschina.org/configuration/optimization/
常用参数:
minSize(默认是30000):形成一个新代码块最小体积;
minChunks(默认是1):在分割之前,这个代码最小应该被引用的次数(注:保证代码块复用性,默认配置的策略是不需要引用也可以被分割);
maxInitialRequests(默认是3):一个入口最大的并行请求数;
maxAsyncRequests(默认是5):按需加载时候最大的并行请求数;
chunks(默认是async):表示显示块的范围,有三个可选值:initial(初始块)、async(按需加载块)、all(全部块),默认为all;
test:用于控制哪些模块被这个缓存组匹配到。原封不动传递出去的话,它默认会选择所有的模块。可以传递的值类型:RegExp、String和Function;
name(打包的chunks的名字):字符串或者函数(函数可以根据条件自定义名字);
priority:缓存组打包的先后优先级。
二、示例
示例工作区间的文件结构:
//工作区间 src//文件夹 module.js//自定义公共模块 subPageA.js//业务逻辑代码A subPageB.js//业务逻辑代码B pageA.js//业务A的入口js pageB.js//业务B的入口js node_modules//打包环境公共包文件 lodash//lodash库的包 package.json//配置环境信息 webpack.config.js//打包配置文件
各个文件的代码(示例中只给出依赖关系):
module.js: export default 'module'; ;
PageA.js: import './subPageA'; var lodash = require('lodash'); ;
PageB.js: import './subPageB'; var lodash = require('lodash'); ;
subPageA.js: import './module'; export default 'subPageA'; ;
subPageB.js: import './module'; export default 'subPageB'; ;
打包配置文件webpack.config.js:
var path = require('path'); module.exports = { entry:{ pageA:'./src/pageA.js', pageB:'./src/pageB.js' }, output:{ path:path.resolve(__dirname,'dist'),//构建文件夹 filename:'[name][hash:5].bundle.js',//生成文件名称 chunkFilename:'[name][hash:5].js' }, optimization:{//webpack4新增 splitChunks:{//可以在这里直接设置抽离代码的参数,最后将符合条件的代码打包至一个公共文件 cacheGroups:{//设置缓存组用来抽取满足不同规则的chunk,下面以生成common、vender为例 // 根据不同的参数设置抽取不同条件的公共js common:{// name:'common', chunks:'all', minSize:1, minChunks:1, priority:1//设置匹配优先级,数字越小,优先级越低 }, vendor:{ name:'vender', test:/[\\/]node_modules[\\/]/,//匹配node模块中匹配的的模块 priority:10,//设置匹配优先级,数字越大,优先级越高 chunks:'all' } } } }, mode:'development' }
在示例中,以test作为提取条件,在priority:10大于priority:1的条件下优先提取了lodash并命名为vender作为一个公共js,然后再提取module.js,即使是lodash还符合common的提取条件,但由于已经有优先级高的提取了这部分代码,就不会再重复提取。
关于webpack提取js代码优化操作还有其他特性和参数没有在示例中展示,需要进一步学习和了解webpack的打包操作建议参考前文中提供的手册链接。