Webpack 性能优化 二次编译速度提升3倍!

本文作者为 360 奇舞团前端开发工程师 Rien.

本篇文章主要记录 webpack 的一次性能优化。

现状

随着业务复杂度的不断增加,项目也开始变得庞大,工程模块的体积也不断增加,webpack 编译的时间也会越来越久,我们现在的项目二次编译的时间在 5s到6s 之间,对于我们迭代速度非常快的项目来说,二次编译时间长会导致效率非常低下。优化的手段有很多,之前项目原本已经做了很多如环境分离、并行编译等优化,本文从几个小的角度进行二次编译的优化讲解,大家也可以检查一下自己的项目能否从以下几个方面进行优化。

更改source map配置

首先,介绍一款插件webpack.ProgressPlugin。官网给出的解释是

The ProgressPlugin provides a way to customize how progress is reported during a compilation.

也就是说,ProgressPlugin可以监控各个hook执行的进度,输出各个hook的名称和描述,输出构建进度。通过插件webpack.ProgressPlugin对webpack整个运行做了分析,发现耗时较长的阶段主要是生成sourceMap文件的阶段:

通过查阅sourcemap的配置,发现了问题是因为devtool配置为source-map的原因。之前的同学使用source-map可能是因为要做一些其他的处理,需要用到源码,现在并无此需要。Webpack支持sourceMap20+种不同的方式,通过关键字组合,可以生成用于各种场景的sourcemap。每种方式的速度和效果各不相同。效果最好的速度最慢。

在这里我贴了一张官网截图的对比图:

从上图我们可以看到webpack为sourcemap提供的一些关键字,而sourcemap模式都是左边介绍的关键字进行拼接构成。

上图是一些不同配置项的对比,可以看到其中一些值适用于开发环境,一些适用于生产环境。
对于开发环境,通常希望更快速的sourcemap,需要添加到bundle中以增加体积为代价,但是对于生产环境,则希望更精准的sourcemap,需要从bundle中分离并独立存在。在开发环境下使用eval-cheap-module-source-map(webpack推荐方式)大大减少了这一阶段的耗时,同时对开发体验及错位定位影响较小。
这里顺便提一下,生产模式我们可以使用:none,因为SourceMap会暴露源代码;调试是开发阶段的事情。如果对代码实在没有信心可以使用nosources-source-map。sourcemap里是有sourceContent部分的,也就是直接把源码贴在这里,这样的好处是根据文件路径查不到文件也可以映射,但这样会增加sourcemap的体积,也会暴露源码。加上 nosources之后,生成的sourcemap就没有sourceContent部分了,sourcemap文件大小会小很多,也不会暴露源码。

Html-webpack-plugin的升级

经过上面的优化 二次编译的时间有了较大的提升 。但是通过观察分析,发现html-webpack-plugin耗时不太正常,因为html-webpack-plugin 的作用很简单,就是:使用 webpack打包时创建一个 html 文件,并把 webpack 打包后的静态文件自动插入到这个 html 文件当中。我们已经从全量的8个页面改为增量单个html启动了耗时不应该那么久。

经过排查及github issue里看到,是当前插件版本有一些性能问题。

从v3改为v4版本后 这个插件的耗时从秒级降为毫秒级。

ESlint-loader 去除

后续我发现在对不同文件模块进行更改时,编译时间有较大的差异,通过插件speed-measure-webpack-plugin对插件、loader耗时分析发现,部分loader运行时间不一致,编译慢是由eslint-loader导致的。

项目之初,每个文件的代码量基于规范不会太大,在开发过程中使用eslint-loader进行代码规范校验,后续随着需求迭代,可能因为时间或者历史的原因,没有对单个文件的代码量做限制,导致部分功能模块代码量巨大,在开发这一块内容的时候,eslint-loader对整个文件进行校验,耗时较长。

由于

  1. eslint无法从根本上解决代码逻辑上的质量问题
  2. eslint-loader已废弃。所以这里就把eslint-loader暂时去掉了。

通过去除eslint-loader,在部分大文件改动时,编译时间有了较大提升。

为了弥补代码规范的问题,不经过eslint-loader进行校验,我们可以在本地开发的时候,使用vscode的 eslint插件进行代码校验,规范调整。但是这里只是口头约定,后续可以使用git钩子结合eslint在代码提交的时候做强制校验。

总结

经过一系列优化,最终我们得到,在改动同一大文件的基础上,二次编译时间得到了大幅度提升,改善了开发效率和体验。将近提升3倍。

- END -


360 W3C ECMA TC39 Leader 注和加


相关推荐

  • 24K Star开源工具:让键盘与鼠标跨越边界,无缝共享,开创高效办公模式
  • 利润预测不再困难,scikit-learn线性回归法让你事半功倍
  • 破解自注意力推理缺陷的奥秘,蚂蚁自研新一代Transformer或实现无损外推
  • 全新近似注意力机制HyperAttention:对长上下文友好、LLM推理提速50%
  • GPT-4V数学推理如何?微软发布MathVista基准,评测报告长达112页
  • 连葫芦娃都数不明白,解说英雄联盟的GPT-4V面临幻觉挑战
  • 各路大神献出自定义GPT,24小时Top 9名单在这
  • 连字节跳动都跳不动了!
  • 仅融2轮估值900亿,宁波独角兽要IPO了
  • GPT-4 帮助员工绩效提升 40%!
  • 年薪超80万美元,成为全美收入最高的1%后,Meta前技术主管亲述晋升经历:我曾与焦虑作斗争!
  • 【ICCV2023】MMVP:基于运动矩阵的视频预测
  • 做科研,常用工具箱!
  • 图解Numpy,这篇文章是真的强!
  • 得物一面:Redis大key有什么危害?如何排查和处理?
  • NGINX 模块现在可以用 Rust 编写了
  • 百度智能云千帆官方出品精选系列课程来了!百度算法工程师从 0-1 教你搭建 AI 原生应用 | Q推荐
  • AI 辅助编程何去何从,听听这 20+ 公司的研发 1 号位怎么说?
  • 阿里云突发严重故障,淘宝、闲鱼、阿里云盘、钉钉“崩”上热搜!历经 2.5 小时恢复
  • 丢掉 LangChain、像 Docker一样编排大模型应用程序:这支十余人的年轻创业团队如何在2个月做出一个LLMOps平台?