基于CommonsChunkPlugin,webpack打包优化

前段时间一直在基于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筛选出affectedChunks
12                      * 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                                 targetChunk
30                             );
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才能加载chunksWithExtractedModules
50                         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`) !== -1
13                         )
14                 ) {
15                     return true
16                 }
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 true
34                 }
35                 return false;
36             }
37         }),
38         new webpack.optimize.CommonsChunkPlugin({
39             async: ‘async‘,
40             minChunks: 2
41         }),

  

原文地址:https://www.cnblogs.com/legu/p/8359898.html

时间: 2024-08-01 13:01:02

基于CommonsChunkPlugin,webpack打包优化的相关文章

[转] Webpack 打包优化之体积篇

谈及如今欣欣向荣的前端圈,不仅有各类框架百花齐放,如Vue, React, Angular等等,就打包工具而言,发展也是如火如荼,百家争鸣:从早期的王者Browserify, Grunt,到后来赢得宝座的 Gulp, 以及独树一帜的 fis3, 以及下一代打包神器 Rollup :在 browserify,grunt,gulp,rollup,webpack 可以一窥其中部分对比.在本文要探究的是,当前打包工具绝对霸者 Webpack. Webpack Package optimization W

Webpack 打包优化之体积篇

谈及如今欣欣向荣的前端圈,不仅有各类框架百花齐放,如Vue, React, Angular等等,就打包工具而言,发展也是如火如荼,百家争鸣:从早期的王者Browserify, Grunt,到后来赢得宝座的 Gulp, 以及独树一帜的 fis3, 以及下一代打包神器 Rollup :在 browserify,grunt,gulp,rollup,webpack 可以一窥其中部分对比.在本文要探究的是,当前打包工具绝对霸者 Webpack. Webpack Package optimization W

(webpack系列二)webpack打包优化探索

虽然webpack的已经升级到了webpack4,而我们目前还在使用webpack3,但其中的优化点都大同小异,升级后同样适用. 性能优化初步原则 减小代码量 减小请求数 最大化利用浏览器缓存 这三条原则永远是一切优化的前提 优化配置 升级webpack 3,优化js的编译能力(Scope Hoisting) 1// 主要配置2plugins:[3  new webpack.optimize.ModuleConcatenationPlugin()4] 合理规划 entry 入口配置(平衡vend

webpack打包优化并开启gzip

应用场景:项目使用webpack2.x进行打包,打包后静态资源通过nginx转发配置: 问题:webpack打包后的资源文件特别,特别大,没打包之前页面一个页面js有2M左右(其中已经抽离了css)? 优化一:一看js这么大肯定是没有关闭source-map,先将webpack配置文件中dev-tool:false, 优化二:使用compresion-webpack-plugin插件将静态资源压缩,并生成.gz文件,配置如下: 具体用法请参照:http://www.css88.com/doc/w

Vue发布过程中遇到坑,以及webpack打包优化

前言 这段时间,本人自己做了一个vue画面部署到自己的服务器上,发现运行速度慢的的惊人,虽然服务器很渣(本人没什么钱,只能租最差的服务器,主要是给自己学习用的),但是这样开发出来的网站简直不能用,所以就查阅各种资料和网站,一步一步把代码包优化.这篇文章主要是把我调优的过程记录下来. 项目的基础框架是通过TypeScript官网取得的.各种基础框架模版 项目的构成 vue + ant-design + mysql + TypeScript vue项目地址 最后,关于如何在vue里面实现按需加载,请

webpack打包优化

vue-cli3 webpack优化 . 开启Gzip压缩 vue.config.js webpack配置 安装包 npm install compression-webpack-plugin -D const CompressionWebpackPlugin = require('compression-webpack-plugin') module.exports = { configureWebpack: config => { // 开发环境不需要gzip if (process.env

webpack打包优化之react-router路由分割

我们在用react全家桶做项目打包出来的文件是全部打包在一起的,(js一个文件,css一个文件),这样进入首页之后全部加载出来.这样在一个小的项目时没有问题,但是在手机端或者是在pc端比较大的项目,首屏加载时间很慢见识一个很大的问题,会影响用户的使用体验,那么接下来讲一线解决方法 首先想一下要如何解决,要是首屏只加载一些必要的资源,在路由变化时在加载相应的打包文件,这样就可以了.那要如何做呢,这就要来说以下路由分割了,路由分割就是根据路由打包出相应的包,然后在路由变换时在加载这个路由对应的包.接

Webpack打包进阶

说在前面 由于使用了React直出,页面各项性能指标使人悦目.本篇将深入探讨目前PC部落所采用webpack打包优化策略,以及探讨PC部落并未使用的 webpack Code Splitting 代码分包.异步模块加载特性.看看它们又是如何对PC部落的性能起到进一步的催化作用. 为什么要使用webpack 如果你曾经使用过 Broserify, RequireJS 或类似的打包工具,并注重:代码分包.异步加载.静态资源打包(图片/CSS).那么 webpack 就是帮你构建项目的利器!简单一句话

webpack打包经验——处理打包文件体积过大的问题

前言 最近对一个比较老的公司项目做了一次优化,处理的主要是webpack打包文件体积过大的问题. 这里就写一下对于webpack打包优化的一些经验. 主要分为以下几个方面: 去掉开发环境下的配置 ExtractTextPlugin:提取样式到css文件 webpack-bundle-analyzer:webpack打包文件体积和依赖关系的可视化 CommonsChunkPlugin:提取通用模块文件 提取manifest:让提取的公共js的hash值不要改变 压缩js,css,图片 react-