一次webpack小规模优化经历
这标题一点营销号味道都没有,怎么会有人看啊!(笑)
没人看也无所谓的文章背景:
八月份入职了新公司,是个好几年的老项目了,公司产品是存在很久了,但我接触到的代码版本保守估计应该是有个三年到四年这样的历史,所以期间应该是换工具重构了一遍。公司最开始没前端,然后不知道哪位大哥建项目的时候选择建成多页面应用,分功能模块打包,后来被招我进来的大哥(也是前端的负责人)改成了单页面应用,但因为改造不完整,导致留下了些后遗症,表面上主要体现在热重载速度极慢,以及打包体积巨大、编译耗时长,jenkins完整推一次包要差不多半小时;在这种优化已经成为刚需的前提下,虽然组里有三四个前端同事,但他们好像都没想过去搞这种事情,在我加入后不久,前端的负责人就离职了...没有形式上的领导,更不会有人想着去做这种耗时不确定的还不一定会有效果的事情。公司对新人的期待并没有那么迫切,所以前期基本上除了日常安排的功能开发之外基本上是放养状态,进公司一个月后,按惯例经理跟前端负责人(彼时前端大哥还没离职)要找新人做个谈话,了解一些融入状态以及这段时间内的工作内容,我就提到了公司项目目前的这些硬伤和优化的想法,在得到授意之后,日常开发之余,就进行优化工作。
基本配置(优化前): 前端框架vue2.5.x+element-ui,构建工具webpack1.x+gulp, express+中间件实现der-server
正文:
前面说了那么多无关紧要的,可没打算跑题,本文意为抛砖引玉,从个人的实践触发,通过具体的一些优化操作,总结一下优化思路,期待能与各位同道交流学习。
那么我们现在开始。
既然已经存在问题,而需求则是提高开发体验、减小打包体积与编译耗时,那么在这个前提下,个人认为做优化的第一步,是分析问题,大体上来说,评估一个前端包质量的多种维度中,打包速度跟包体积这些指标是比较直观的,所以接下来我打算介绍两个插件speed-measure-webpack-plugin与webpack-bundle-analyzer,量化分析打包耗时和前端包体积,用来帮助我们找到优化的正确方向。
那么我先拿入职时候接手的项目代码开始做可视化的分析。
(多图警告)
首先我们在管理生产模式的配置文件webpck.prod.conf的代码中添加这两个插件:

然后跑一遍打包命令,项目打包后,资源的视图关系是这样类似echarts的treemap的结构:

而负责速度分析的插件speed-measure-webpack-plugin也在控制台输出了他的统计情况:

dist目录50M,耗时约270s,前端页面其实不是特别多,所以这个成绩可以说惨不忍睹,那么接下来我们单纯从视图上来分析,看看能不能找出一些异常。
webpack-bundle-analyzer的分析结果有三个维度,stat\parsed\Gzipped;
对于这三个维度,官方的解释为
stat
This is the "input" size of your files, before any transformations like minification.
It is called "stat size" because it's obtained from Webpack's stats object.
parsed
This is the "output" size of your files. If you're using a Webpack plugin such as Uglify, then this value will reflect the minified size of your code.
gzip
This is the size of running the parsed bundles/modules through gzip compression.
可以理解为分别对应着webpack从入口文件打包递归到的所有模块体积、解析与代码压缩优化后输出到dist目录的体积、开启Gzip之后的体积,后两个维度的值一般来说接近真实的前端包体积,但不会跟他们占用的硬盘空间完全一致,随优化手段不同也有所差异。
现在这个项目的stat状态下体积为: ……接近400M

同时,我们可以发现有多个bundle存在结构相似的情况,比如:

查询一个被多个文件引用的普通页面组件,能看到这个源文件被打包进多个bundle:

而之前的另一份截图也表示用于压缩css代码的extract-text-webpack-plugin与用于压缩js代码的UglifyJsPlugin,在打包过程中的大部分时间里保持着运作,总结以上几个现象,可以得出这么一个观点:有一部分公共模块,没有正确地被提取出来;
而在webpack4以下,官方提供的负责提取公共模块的插件为:webpack.optimize.CommonsChunkPlugin,而这是我当前的CommonsChunkPlugin配置:

第一个commons chunk的含义是从根目录下的node_modules目录去抽取所有被引用的js文件,这个chunk被命名为vendor,无引用次数限制;
第二个commons chunk的含义是从刚刚定义vendor的chunk中抽取公共模块,默认minChunk是2
这两个chunk都是针对node_modules的第三库进行公共模块抽取,而缺少了对项目自建公共模块的管理,因此我们尝试着添加一个新的commons chunk:
new webpack.optimize.CommonsChunkPlugin({
name: 'index',
async: true,
children: true,
}),
加上这段配置后,重新打包,这回看起来就比较正常了:

速度虽然还是比较慢,但相比之前,也不是那么难以接受:

到这里体积跟编译时间这两个痛点就算是解决了,我在做完这个版本的优化后,项目暴露出来比较明显的还有一些问题:
1.浏览器首屏加载速度一般,单个文件体积过大,常导致单个资源请求耗时较长
2.开发环境下项目启动/热重载还是很慢,我对中间件+本地起服务那一套不怎么熟,个人在短时间内没找到突破口
第一个问题关系到业务需求、以往业务代码写法还有webpack拆包,而由于以上的第二个问题,开发体验还是没有得到提升,单个文件改动触发的热重载耗时动辄十多秒,着实有些折磨,所以在完成第一个版本不久,我决定在这个基础之上升级构建工具,webpack1.x升级到4.x的过程中也遇到了很多坑,这些我打算整理一下再更新到下期的内容中。
关于可视化分析的工具,还有多种选择,比如:
webpack自己的可视化分析工具(线上):https://webpack.github.io/analyse/
仪表盘形式的webpack-dashboard: https://github.com/Exodia/webpack-dashboard
同样是仪表盘形式,但视觉效果更出色,下载量也在慢慢增长的:https://github.com/zouhir/jarvis
ok,我们有机会——当然有机会——所以我们下期内容再见——下周开始出差,希望目的地那边不会那么忙。
——“虽然我在经济舱”!
一次webpack小规模优化经历的更多相关文章
- 记一次真实的webpack优化经历
前言 公司目前现有的一款产品是使用vue v2.0框架实现的,配套的打包工具为webpack v3.0.整个项目大概有80多个vue文件,也算不上什么大型项目. 只不过每次头疼的就是打包所耗费的时间平 ...
- webpack性能优化——DLL
Webpack性能优化的方式有很多种,本文之所以将 dll 单独讲解,是因为 dll 是一种最简单粗暴并且极其有效的优化方式. 在通常的打包过程中,你所引用的诸如:jquery.bootstrap.r ...
- SQL 优化经历
一次非常有趣的 SQL 优化经历 阅读本文大概需要 6 分钟. 前言 在网上刷到一篇数据库优化的文章,自己也来研究一波. 场景 数据库版本:5.7.25 ,运行在虚拟机中. 课程表 #课程表 cr ...
- sql优化经历(转存+记录)
sql优化经历 补充:看到这么多朋友对sql优化感兴趣,我又重新补充了下文章的内容,将更多关于sql优化的知识分享出来, 喜欢这篇文章的朋友给个赞吧,哈哈,欢迎交流,共同进步. 2015-4-30补充 ...
- 一次mysql优化经历
某日运维突然说无线终端的频道页接口訪问量非常大,memcache缓存扛只是来.导致mysql并发查询量太大,导致server不停地宕机,仅仅能不停地重新启动机器.遗憾的是运维并没有告诉mysql查询量 ...
- Webpack 打包优化之速度篇
在前文 Webpack 打包优化之体积篇中,对如何减小 Webpack 打包体积,做了些探讨:当然,那些法子对于打包速度的提升,也是大有裨益.然而,打包速度之于开发体验和及时构建,相当重要:所以有必要 ...
- Webpack 打包优化之体积篇
谈及如今欣欣向荣的前端圈,不仅有各类框架百花齐放,如Vue, React, Angular等等,就打包工具而言,发展也是如火如荼,百家争鸣:从早期的王者Browserify, Grunt,到后来赢得宝 ...
- webpack 性能优化 dll 分包
webpack 性能优化 dll 分包 html-webpack-externals-plugin DLLPlugin https://www.webpackjs.com/configuration/ ...
- webpack打包优化点
目录 1. noParse 2. 包含和排除目录 3. IgnorePlugin 4. happypack 5. DllPlugin动态链接库 6. 热更新 7. 开发环境 tree-shaking ...
随机推荐
- 联赛模拟测试17 A. 简单的区间 启发式合并
题目描述 分析 我们要找的是一段区间的和减去该区间的最大值能否被 \(k\) 整除 那么对于一段区间,我们可以先找出区间中的最大值 然后枚举最大值左边的后缀与最大值右边的前缀之和是否能被 \(k\) ...
- spring boot:thymeleaf给fragment传递参数的方法(spring boot 2.3.3)
一,thymeleaf如何给fragment传递参数? 1,如果是全局的参数,可以用interceptor中传递 非全局参数,可以从controller中传递 2,引用片断时也可以传递参数 说明:刘宏 ...
- centos7下面 es7.5 搭建
centos6 搭建 参考 https://www.cnblogs.com/php-linux/p/8758788.html 搭建linux虚拟机 https://www.cnblogs.com/ph ...
- 运行bee run之后出现的错误以及解决方法Failed to build the application:
运行bee run之后出现的错误以及解决方法 创建一个beego项目 bee new myapp 在该项目执行下面的代码 bee run 出现的问题 2020/04/22 21:12:07 INF ...
- go内建方法 new和make区别
package mainimport ( "fmt" "reflect")func main() { // make函数 //makeSlice() // 创建 ...
- 【服务总线 Azure Service Bus】ServiceBus 队列中死信(DLQ - Dead Letter Queue)问题
Azure Service Bus 死信队列产生的原因 服务总线中有几个活动会导致从消息引擎本身将消息推送到 DLQ. 如 超过 MaxDeliveryCount 超过 TimeToLive 处理订阅 ...
- Afinal简介和使用方法
Afinal简介 Afinal 是一个android的sqlite orm 和 ioc 框架.同时封装了android中的http框架,使其更加简单易用: 使用finalBitmap,无需考虑bitm ...
- VirtualXposed结合justTrustMe 模块傻瓜式破解app没法抓包问题
一.首先就是按照这两个apk 声明仅供学习 justTrustMe 链接:https://pan.baidu.com/s/1av3oaez4y4n6a9C1I0VsAg 提取码:mjqg Virtua ...
- # ThreeJS学习7_裁剪平面(clipping)
ThreeJS学习7_裁剪平面(clipping) 目录 ThreeJS学习7_裁剪平面(clipping) 1. 裁剪平面简介 2. 全局裁剪和局部裁剪 3. 被多个裁剪平面裁剪后 4. 被多个裁剪 ...
- 分布式雪花算法获取id
实现全局唯一ID 一.采用主键自增 最常见的方式.利用数据库,全数据库唯一. 优点: 1)简单,代码方便,性能可以接受. 2)数字ID天然排序,对分页或者需要排序的结果很有帮助. 缺点: 1)不同数据 ...