前言

在前端工程的的打包史中,common文件向来都不是一个好处理的方面。在这一块,webpack提供了CommonsChunkPlugin来处理这个事情,但是在由于文档的模棱两可,再加上各种配置选项的多样性和某些bug,还是有不少坑的。

分析包

所谓工欲善其事必先利其器,我们既然想做common方面的优化,那么首先肯定要知道打包后的文件体积庞大的主要原因。说到这里就不得不提到一个相当好用的工具:webpack-bundle-analyzer

它既是一个webpack插件,又是一个命令行工具。能够将webpack包的内容转换成可缩放的树状图,方便进行交互分析。恩。。。就是这玩意:

安装

npm install --save-dev webpack-bundle-analyzer

作为插件使用

webpack.config.js中:

var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;// ...
plugins: [new BundleAnalyzerPlugin()]
// ...

默认配置如下:

new BundleAnalyzerPlugin({// Can be `server`, `static` or `disabled`.// In `server` mode analyzer will start HTTP server to show bundle report.// In `static` mode single HTML file with bundle report will be generated.// In `disabled` mode you can use this plugin to just generate Webpack Stats JSON file by setting `generateStatsFile` to `true`.analyzerMode: 'server',// Host that will be used in `server` mode to start HTTP server.analyzerHost: '127.0.0.1',// Port that will be used in `server` mode to start HTTP server.analyzerPort: 8888,// Path to bundle report file that will be generated in `static` mode.// Relative to bundles output directory.reportFilename: 'report.html',// Automatically open report in default browseropenAnalyzer: true,// If `true`, Webpack Stats JSON file will be generated in bundles output directorygenerateStatsFile: false,// Name of Webpack Stats JSON file that will be generated if `generateStatsFile` is `true`.// Relative to bundles output directory.statsFilename: 'stats.json',// Options for `stats.toJson()` method.// For example you can exclude sources of your modules from stats file with `source: false` option.// See more options here: https://github.com/webpack/webpack/blob/webpack-1/lib/Stats.js#L21statsOptions: null,// Log level. Can be 'info', 'warn', 'error' or 'silent'.logLevel: 'info'
})

命令行使用

第一步:

webpack --profile --json > stats.json

第二步:

webpack --profile --json | Out-file 'stats.json' -Encoding OEM

执行成功后,你将看到以下动态网页:

在这里顺便放上线上文件加载waterfall,作为对比。

问题

通过图表可以看到,在以下配置下:

config.plugins.push(new CommonsChunkPlugin('commons', 'js/commons.[hash].bundle.js'));

打包出来的文件还是有很多问题的:

  • common包规划不合理, swiper.js ,area.json等公用文件大量重复加载。

  • antd 没有抽离出来,无法并行加载,也无法进一步做运行时按需加载。

  • echarts在每个使用的包都单独打包一份,只要包含echarts的包,基本一百多kb。(线上压缩并开启gzip)

  • import {ImgBigSwiper} from 'components/src/index'; 这种写法会导致将components里面的所有组件全部打包进页面的js。应该这样写:import ImgBigSwiper from 'components/src/ImgBigSwiper';挨个引入,见webpack将ES6编译成CommonJs后只引入用到的模块

  • common.js独占490kb,要等这个包加载完后index才开始解析路由。

在这个过程中,会发现一个有趣的事情。就是index.html页面的script加载分为以下两个部分:

......
<script type="text/javascript" src="//res.dinghuo123.com/src/common/ueditor/ueditor.config.js"></script>
<script type="text/javascript" src="//res.dinghuo123.com/src/common/ueditor/ueditor.config.js"></script>
<script type="text/javascript" src="//res.dinghuo123.com/src/common/ueditor/ueditor.config.js"></script>
......
<script>document.write('<script src="https://resource.dinghuo123.com/dist/ydhv2/webpack.assets.js?v=' + Math.random() + '"><\/script>');document.write('<script src="' + window.WEBPACK_ASSETS['commons'].js + '"><\/script>');document.write('<script src="//res.dinghuo123.com/src/common/ueditor/ueditor.config.js"><\/script>');document.write('<script src="' + window.WEBPACK_ASSETS['index'].js + '"><\/script>');
</script>

然后你会发现,是上面一块的script并行加载完,才并行加载下一个script标签的内容。大家可以思考一下为什么。

改进配置

进过调整之后的CommonsChunkPlugin配置:

config.plugins.push(new CommonsChunkPlugin({name: 'commons',minChunks: Infinity // 随着 入口chunk 越来越多,这个配置保证没其它的模块会打包进 公共chunk
}));config.plugins.push(new CommonsChunkPlugin({async:'antd',minChunks(module) {var context = module.context;return context && context.indexOf('antd/dist') >= 0;}
}));config.plugins.push(new CommonsChunkPlugin({async:'echarts',minChunks(module) {var context = module.context;return context && (context.indexOf('echarts') >= 0 || context.indexOf('zrender') >= 0);}
}));

这里用到了minChunks和async两个配置。

minChunks

其中第一name的commons是一个entry入口,里面是一个依赖包的数组。minChunks设置为Infinity这个配置保证没其它的模块会打包进 公共chunk。因为说实话,CommonsChunkPlugin的commons分析实在是不怎么只能,还是手动控制会更好一些。
当然,你可以传入一个 function ,以添加定制的逻辑(默认是 chunk 的数量),这个函数会被 CommonsChunkPlugin 插件回调,并且调用函数时会传入 module 和 count 参数。
module 参数代表每个 chunks 里的模块,这些 chunks 是你通过 name/names 参数传入的。

  • module.context: The directory that stores the file. For example: '/my_project/node_modules/example-dependency'

  • module.resource: The name of the file being processed. For example: '/my_project/node_modules/example-dependency/index.js'

  • count 参数表示 module 被使用的 chunk 数量。

当你想要对 CommonsChunk 如何决定模块被打包到哪里的算法有更为细致的控制, 这个配置就会非常有用。

async

下面的内容是官网弄过来的,其实我也看不太懂。。。

如果设置为 true,一个异步的 公共chunk 会作为 options.name 的子模块,和 options.chunks 的兄弟模块被创建。它会与 options.chunks 并行被加载。可以通过提供想要的字符串,而不是 true 来对输出的文件进行更换名称。

结果

还是先看打包分析的结果吧:

通过上面分析可以看到:

  1. common合理划分,抓大放小。

  2. antd和echarts提取出来,并行加载。

  3. components 用到什么打包什么。(手动控制的)

  4. 大大减小了其他业务包的体积,93%的业务包大小控制在25K以内,剩下7%的业务包大小控制在50k以内。(开启gzip)

  5. 首屏加载资源的总大小几乎没有变化。

接下来的方向

  1. echarts 和Ueditor运行时按需加载。

  2. tree-shaking的探索

参考

Vendor and code splitting in webpack 2
webpack 按需打包加载
weboack Split app and vendor code
awesome-webpack-cn

webpack的CommonsChunkPlugin分析与优化相关推荐

  1. 性能分析--视图优化

    性能分析/性能优化-视图优化 优化概述 流畅的操作体验 卡顿 稳定性 内存泄漏,崩溃 省电省流量 代码质量,逻辑 安装包小 安装包过大 UI优化 View层级相同的情况下,尽量使用LinearLayo ...

  2. 基于linux服务器的性能分析与优化

    基于linux服务器的性能分析与优化 方面:硬件系统软件网络 现象:系统不稳定相应速度慢 web无法打开打开速度慢 方案:硬件故障更换硬件或升级硬件 系统问题修改系统参数和配置 软件问题修改和升级软件 ...

  3. mysql性能优化-慢查询分析、优化索引和配置

    目录 一.优化概述 二.查询与索引优化分析 1性能瓶颈定位 Show命令 慢查询日志 explain分析查询 profiling分析查询 2索引及查询优化 三.配置优化 1)      max_con ...

  4. RK2908开机时间分析及优化

    1    RK2908开机时间分析和优化文档背景概述      目前由于RK2908开机时间比较长(平均35s)可能对一体机项目的整体体验造成影响,所以需要对RK2908开机整个流程进行分析,是否有优 ...

  5. 三个步骤分析网站优化程度

    三个步骤分析网站优化程度 分析是做好seo优化必备工作之一!只有事前做好了充足的分析工作才能让网站的后期优化工作畅通无阻!那么如何细致的分析网站呢?!下面福州seo维思和大家分享三个步骤分析网站优化程 ...

  6. 排序算法 | 快速排序,算法的图解、实现、复杂度和稳定性分析与优化

    今天讲解一下快速排序算法的原理以及实现.复杂度和稳定性分析与优化 目录 1 快速排序的原理 2 快速排序代码实现 3 复杂度和稳定性分析.优化 4 习题练习 1 快速排序的原理 快速排序是所有内部排序 ...

  7. MySQL索引分析和优化(转)

    MySQL索引分析和优化(转) 索引用来快速地寻找那些具有特定值的记录,所有MySQL索引都以B-树的形式保存.如果没有索引,执行查询时MySQL必须从第一个记录开始扫描整个表的所有记 录,直至找到符 ...

  8. mysql io 100_MySQL服务器 IO 100%的分析与优化方案

    压力测试过程中,如果因为资源使用瓶颈等问题引发最直接性能问题是业务交易响应时间偏大,TPS逐渐降低等.而问题定位分析通常情况下,最优先排查的是监控服务器资源利用率,例如先用TOP 或者nmon等查看C ...

  9. mysql io_MySQL服务器 IO 100%的分析与优化方案

    前言 压力测试过程中,如果因为资源使用瓶颈等问题引发最直接性能问题是业务交易响应时间偏大,TPS逐渐降低等.而问题定位分析通常情况下,最优先排查的是监控服务器资源利用率,例如先用TOP 或者nmon等 ...

  10. 实践App内存优化:如何有序地做内存分析与优化

    由于项目里之前线上版本出现过一定比例的OOM,虽然比例并不大,但是还是暴露了一定的问题,所以打算对我们App分为几个步骤进行内存分析和优化,当然内存的优化是个长期的过程,不是一两个版本的事,每个版本都 ...

最新文章

  1. Android 网络连接--Wifi/3G
  2. 小程序---模板的引用与使用
  3. 学习手记(2019/7/05~2019/8/31)——快乐暑假
  4. 2c语言程序设计_大学生学C语言的理由是什么
  5. 计算机access数据库,部署 Access 应用程序
  6. docker alpine wkhtmltopdf
  7. SecondaryNameNode的Inconsistent checkpoint fields异常
  8. StoryBoard和代码结合 按比例快速兼容iPhone6/6 Plus教程
  9. ae制h5文字动画_利用AE表达式制作文字弹跳动画
  10. Django Views: Dynamic Content
  11. Oracle11g下导入SDO_GEOMETRY类型的数据异常处理
  12. C/C++编程刷题分享—常见的经典面试题一
  13. 记一次海康威视笔试题小练手
  14. Android 仿淘宝详情视频图片混合轮播
  15. 这家小米生态链公司用AI+学习,重塑儿童手表市场
  16. 爬虫学习,尝试爬取小说网站
  17. 苹果iPhone XS Max 贴膜之后面容无法使用
  18. Softcam虚拟摄像机下载破解和使用
  19. 片偏移怎么计算_桥架水平45度弯头做法(图解)及槽式桥架计算公式
  20. cocos2dx - PageView

热门文章

  1. webbrowser只对浏览器外应用程序以及在_常用浏览器大盘点!
  2. MySQL使用规范手册,程序员必知必会
  3. PHP分批次处理数据
  4. HTML5 拖放(Drag 和 Drop)
  5. $.ajax()常用属性
  6. Xcode添加include目录
  7. undefined reference to `gdk_monitor_get_scale_factor/gtk_widget_get_scale_factor‘
  8. CUPS搜索添加打印机的范例代码
  9. error C2664: “StrCmpW”: 不能将参数 2 从“const char [12]”转换为“PCWSTR”
  10. 使用VS2015编译OpenJDK8