去骨鸡腿排

there's million I can see, only one shines for me

导航

一次webpack小规模优化经历

这标题一点营销号味道都没有,怎么会有人看啊!(笑)
没人看也无所谓的文章背景:

  八月份入职了新公司,是个老项目了,公司产品是存在了很久,但我接触到的代码版本估计应该是只有个2年到3年前的提交记录,所以期间应该是换工具重构了一遍。产品最开始是多页面vue应用,分功能模块打包,后来被把我招进来的大哥(也是前端的负责人)改成了单页面应用,但改造应该是不太完整,导致留下了些后遗症,表面上主要体现在热重载速度极慢,以及打包体积巨大、编译耗时长,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,我们有机会——当然有机会——所以我们下期内容再见——下周开始出差,希望目的地那边不会那么忙。

 

  ——“虽然我在经济舱”!

posted on 2020-11-19 16:31  去骨鸡腿排  阅读(1675)  评论(4编辑  收藏  举报