测量webpack编译速度
有多个同事反应公司打包脚本本地开发时非常慢, 我debug了一下确实找到了个之前没被发现的问题.
而如何知道webpack编译过程卡在了哪里就成了问题.
从webpack进度条看, 只能知道卡了, 而不知道哪个地方卡了, 所以也无从优化.
使用measure-webpack-plugin
使用measure-webpack-plugin插件很容易, 可以不传任何参数, 调用方式也在插件首页介绍了.
无论在本地开发或是打包, 插件都会产生/measureResult.html
文件, 访问他就可以看到编译速度统计.
使用插件后我发现了本地开发时antd.less
因为webpack-chain的社区版本(支持webpack5)有bug, 导致修改参数的行为让less-loader加载了2次, 增加了40秒loader运行时间.
插件原理
从插件源码中看, tap了以下hook, 并维护了变量来记录时间:
- make.
- seal.
- beginIdle. 到这里, webpack的编译流程已经结束.
在都执行完后, 才会执行processAssets
hook, 在这里输出内容.
另外, make流程中, 每个module也有自己的生命周期, 做了记录可以分析build里每个步骤占用的时间.
- buildModule: 开始module的build.
- beforeLoaders: 执行loader前, 这步离上一步的执行时间很短.
- beforeParse: 执行完loader, 这步离上一步的时间差就是module运行loader的时间.
- beforeSnapshot: 执行完parse, parse是从ast里找出依赖的过程, 速度和module的复杂程度有关.
- succeedModule: module的build完成.
开发中的难点
一开始是参考了webpack的progress插件, 比较简单, 具体的可以看我之前的文章.
而发现这些生命周期并不能满足我的需求. 于是自己探索了一些生命周期, 记录在这个地址.
在测试过程中, 发现了很多生命周期之间的速度是很快的, 在大多模块都几乎是0, 所以就精简留了几个重要的.
而进入make环节, 就比较特殊, 很多操作是进入队列并行的.
尝试设置了compiler.options.parallelism = 1
来控制队列长度. 但还存在问题:
- 进入队列的生命周期还是无效的, 因为队列长度1也只能控制不并行, 入队时间还是会挤在一起.
- 在分析依赖以后, 队列会被加长, 因为有队列嵌套, 所以必须加长才能继续执行.
顺便提一下, parallelism
参数是可以通过webpack.config.js传入生效的, 只是文档里没写.
另外我发现, 在每个module的build流程之间, 会消耗很多时间, 经过2天努力也没找到发生在哪里, 那暂时就认为面对复杂的系统, 从ast里找出依赖会比较花时间.
(本文完)
如果你觉得本文对你有帮助, 你可以请我喝一杯咖啡
本文遵循cc协议
你可以在注明出处和非商用的前提下任意复制及演绎