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 等多种发展方向供员工选择,并辅以提供相应的技术力、专业力、通用力、领导力等培训课程。奇舞团以开放和求贤的心态欢迎各种优秀人才关注和加入奇舞团。

相关推荐
于慨3 分钟前
uniapp+vite+cli模板引入tailwindcss
前端·uni-app
yunvwugua__17 分钟前
Python训练营打卡 Day26
前端·javascript·python
满怀101525 分钟前
【Django全栈开发实战】从零构建企业级Web应用
前端·python·django·orm·web开发·前后端分离
Darling02zjh1 小时前
GUI图形化演示
前端
Channing Lewis1 小时前
如何判断一个网站后端是用什么语言写的
前端·数据库·python
互联网搬砖老肖1 小时前
Web 架构之状态码全解
前端·架构
showmethetime1 小时前
matlab提取脑电数据的五种频域特征指标数值
前端·人工智能·matlab
码农捻旧2 小时前
解决Mongoose “Cannot overwrite model once compiled“ 错误的完整指南
javascript·数据库·mongodb·node.js·express
左钦杨3 小时前
IOS CSS3 right transformX 动画卡顿 回弹
前端·ios·css3
NaclarbCSDN3 小时前
Java集合框架
java·开发语言·前端