前段时间一直在基于webpack进行前端资源包的瘦身。在项目中基于路由进行代码分离,http://www.cnblogs.com/legu/p/7251562.html。但是打包的文件还是很大,特别是通过CommonsChunkPlugin的async:true打包的chunk的公共包不可控。今天就通过CommonsChunkPlugin插件的理解,来优化这个问题
问题描述详细些,我们的打包是基于router进行的chunk分割,比如router有10个,router1,router2用到了echart,所以echart打包到了公共文件async中。但是如果用户通过链接,
第一次直接访问的router3,这样就会先加载公共文件async,可是echart代码其实是多余的,影响到了router3的展现。
一开始遇到这个问题,没想到太好的方法,让echart基于chunk进行按需打包~~实在没办法,最后只能从CommonsChunkPlugin插件的源代码入手,看看有什么启发。
1 ????apply(compiler) { 2 ????????compiler.plugin("this-compilation", (compilation) => { 3 ????????????compilation.plugin(["optimize-chunks", "optimize-extracted-chunks"], (chunks) => { 4 ????????????????/** 5 ?????????????????* 根据chunkNames[options.name, options.names],从chunks中筛选出targetChunks, 没有则使用compilation.addChunk新增 6 ?????????????????* 如果children || async,返回targetChunks = chunks 7 ?????????????????*/ 8 ????????????????const targetChunks = this.getTargetChunks(chunks, compilation, this.chunkNames, this.children, this.async); 9 ????????????????targetChunks.forEach((targetChunk, idx) => {10 ????????????????????/**11 ?????????????????????* 根据selectedChunks【options.chunks】,从chunks筛选出affectedChunks12 ?????????????????????* async || children,返回 affectedChunks = targetChunk.chunks, 如果children = true,进行深度遍历 ?13 ?????????????????????*/14 ????????????????????const affectedChunks = this.getAffectedChunks(compilation, chunks, targetChunk, targetChunks, idx, this.selectedChunks, this.async, this.children, this.deepChildren); 15 ????????????????????let asyncChunk;16 ????????????????????if(this.async) {17 ????????????????????????//如果async==string,进行name筛选18 ????????????????????????asyncChunk = affectedChunks.filter(c => c.name === this.async)[0];19 ????????????????????????if(!asyncChunk) {20 ????????????????????????????/**21 ?????????????????????????????* 根据async创建一个新的chunk,和targetChunk绑定关系22 ?????????????????????????????* asyncChunk.addParent(targetChunk); targetChunk.addChunk(asyncChunk); ?23 ?????????????????????????????*/24 ????????????????????????????asyncChunk = this.createAsyncChunk(25 ????????????????????????????????compilation,26 ????????????????????????????????targetChunks.length <= 1 || typeof this.async !== "string" ? this.async :27 ????????????????????????????????targetChunk.name ? `${this.async}-${targetChunk.name}` :28 ????????????????????????????????true,29 ????????????????????????????????targetChunk30 ????????????????????????????);31 ????????????????????????}32 ????????????????????????targetChunk = asyncChunk;33 ????????????????????}34 ????????????????????// 根据minChunks的设置,遍历affectedChunks的modules,返回符合条件的公共modules集合35 ????????????????????const extractableModules = this.getExtractableModules(this.minChunks, affectedChunks, targetChunk);36 ????????????????????if(this.minSize) {// minSize限制逻辑37 ????????????????????????const modulesSize = this.calculateModulesSize(extractableModules);38 ????????????????????????if(modulesSize < this.minSize)39 ????????????????????????????return;40 ????????????????????}41 ????????????????????// affectedChunks中移除extractableModules中modules的关系,只返回存在公共modules的Chunks集合(removeChunk返回true)42 ????????????????????const chunksWithExtractedModules = this.extractModulesAndReturnAffectedChunks(extractableModules, affectedChunks);43 ????????????????????// 公共的modules 和 targetChunk 绑定关联关系44 ????????????????????// chunk.addModule(module); module.addChunk(chunk);45 ????????????????????this.addExtractedModulesToTargetChunk(targetChunk, extractableModules);46 ????????????????????if(this.filenameTemplate)47 ????????????????????????targetChunk.filenameTemplate = this.filenameTemplate;48 ????????????????????if(this.async) {49 ????????????????????????//被移除modules的Chunk,设置和targetChunk的关系,需要第一个加载targetChunk才能加载chunksWithExtractedModules50 ????????????????????????this.moveExtractedChunkBlocksToTargetChunk(chunksWithExtractedModules, targetChunk);51 ????????????????????????asyncChunk.origins = this.extractOriginsOfChunksWithExtractedModules(chunksWithExtractedModules);52 ????????????????????????return;53 ????????????????????}54 ????????????????????//设置affectedChunks和targetChunk的parent关系55 ????????????????????this.makeTargetChunkParentOfAffectedChunks(affectedChunks, targetChunk); ???????????????????56 ????????????????});57 ????????????????return true;58 ????????????});59 ????????});60 ????}
代码逻辑不是很复杂,主要是chunks之间的关系和chunks与modules之间的关系该怎么去维护,对于不清楚webpack打包机制的人,很难一时间了解。其实我也不很了解。
根据上面我的中文注释,对大家的了解有一些帮助。我们会发现,对我们的问题没有什么直接关系。
回到我们的问题,异步的模块中,共用模块怎么能再进行拆分,把大模块echarts,ace编辑器等进行分开打包,并且能自己处理关系,需要的时候才异步加载进来?
其实最后问题的答案很简单,需要实现自动异步加载,那肯定还是要借助CommonsChunkPlugin的async,我们可以根据实际情况,通过minChunks,把echarts,ace这种大库先进行一次async打包,这样再进行根据router的async打包的时候,自然不会再有echarts,ace了,看下现在的配置
1 ????????new webpack.optimize.CommonsChunkPlugin({ 2 ????????????names: [‘vendor‘, ‘libs‘, ‘manifest‘] 3 ????????}), 4 ????????new webpack.optimize.CommonsChunkPlugin({ 5 ????????????async: ‘brace‘, 6 ????????????minChunks: function(module, count) { 7 ????????????????var path = `/public/node_modules`; 8 ????????????????var resource = module.resource; 9 ????????????????if ( resource && 10 ????????????????????????(11 ????????????????????????????resource.indexOf(`${path}/_brace`) !== -1 ||12 ????????????????????????????resource.indexOf(`${path}/brace`) !== -113 ????????????????????????)14 ????????????????) {15 ????????????????????return true16 ????????????????}17 ????????????????return false;18 ????????????}19 ????????}),20 ????????new webpack.optimize.CommonsChunkPlugin({21 ????????????async: ‘echarts‘,22 ????????????minChunks: function(module, count) {23 ????????????????var path = `/public/node_modules`;24 ????????????????var resource = module.resource;25 ????????????????if ( resource && 26 ????????????????????????(27 ????????????????????????????module.resource.indexOf(`${path}/_echarts`) !== -1 ||28 ????????????????????????????module.resource.indexOf(`${path}/echarts`) !== -1 ||29 ????????????????????????????module.resource.indexOf(`${path}/zrender`) !== -1 ||30 ????????????????????????????module.resource.indexOf(`${path}/_zrender`) !== -1 31 ????????????????????????)32 ????????????????) {33 ????????????????????return true34 ????????????????}35 ????????????????return false;36 ????????????}37 ????????}),38 ????????new webpack.optimize.CommonsChunkPlugin({39 ????????????async: ‘async‘,40 ????????????minChunks: 241 ????????}),
基于CommonsChunkPlugin,webpack打包优化
原文地址:https://www.cnblogs.com/legu/p/8359898.html