【探索源码】html-webpack-plugin 4.x 对多模板下热重载缓慢问题的修复

前言

手上的公司项目热重载一直很慢,每次热重载大概要 15s 左右,最近实在忍无可忍,决定排查一下。html

猜测

项目是基于 vue-cli2 搭建的,前人将 webpack 升级到了 webpack4。出于历史缘由,公司项目的模块是根据模板(.html)划分的,所以项目中存在超过 30 个模板。这让我想起了以前在优化一个 webpack3 项目的时候,也遇到过相似的多模板热重载缓慢的状况,当时是使用 html-webpack-plugin-for-multihtml 库 解决了问题,所以我想,此次会不会也是 html-webpack-plugin 的锅呢?vue

升级 html-webpack-plugin 问题解决

我尝试把 html-webpack-plugin 升级到了最新的 @4.0.0-beta.8 版本,发现热重载速度降到了 1s 左右!webpack

问题解决了,但是其中的原理是什么呢?git

使用 cpuprofile-webpack-plugin 进行性能分析

cpuprofile-webpack-plugin 是一个图形化的 webpack 构建性能分析工具,它会统计构建过程当中每一个插件运行的时间,还会生成整个构建过程的火焰图,以下图,它记录了个人项目使用 html-webpack-plugin@3.2.0 时一次热重载的性能分析:github

cpuprofile-webpack-plugin 分析结果

图:cpuprofile-webpack-plugin 分析结果web

咱们发如今整个 15.94s 的热重载过程当中,html-webpack-plugin 的运行时间占据了 13.51s,能够说几乎所有时间都用在了这上面,这个图也验证了个人猜测。接下来,咱们经过火焰图进一步分析,首先找一个运行时间较长,比较有表明性的 html-webpack-plugin 执行过程:vue-cli

一次时间较长的 html-webpack-plugin 运行

图:一次时间较长的 html-webpack-plugin 运行npm

点击进去,查看更详细的调用栈分析:json

html-webpack-plugin 详细的调用栈分析

图:html-webpack-plugin 详细的调用栈分析函数

发现所有耗时集中在 html-webpack-plugin/index.js -> templateParametersGenerator -> toJson 函数上。

查看源码

首先查看了最新版(4.0.0-beta.8)中 templateParametersGenerator 方法的源码,能够看出它是用来生成 templateParameters 的默认配置的,而在这个版本中它并没有调用 toJson 方法

4.0.0-beta.8 templateParametersGenerator 的调用

图:4.0.0-beta.8 templateParametersGenerator 的调用

4.0.0-beta.8 templateParametersGenerator 的定义

图:4.0.0-beta.8 templateParametersGenerator 的定义

而后回溯 3.2.0 版本以前的提交,终于见到了它的调用,webpack 文档中解释 compilation.getStats().toJson() 是用来生成编译过程的性能分析 json 文件的方法,那么罪魁祸首就是它了。

3.2.0 templateParametersGenerator 的定义

图:3.2.0 templateParametersGenerator 的定义

查找修复这个问题的 commit

后来我尝试了把 html-webpack-plugin 的版本回退到 4.x 的第一个版本 4.0.0-alpha,发现热重载性能依然是没问题的,所以提交的定位就在 3.2.0 到 4.0.0-alpha 之间,通过一番查找,终于找到了这个 fix,出于性能缘由移除 compilation.getStats()

fix: Remove compilation.getStats() call for performance reasons

图:fix: Remove compilation.getStats() call for performance reasons

后记

其实此次排查我也走了很多弯路,以前一直在尝试经过阅读代码查找,找了一天都找不出来,后来使用了性能分析工具才知道本身以前有多蠢 :-)。本文只是给你们讲一个性能分析的故事,为你们提供一些思路,但愿你们的代码都没有bug~

附:html-webpack-plugin 4.x 钩子函数的变动

因为个人代码里踩了这个坑,因此给你们讲一下,html-webpack-plugin 4.x 对钩子函数进行了重构,注意是重构,不是更新,也就是说,虽然名字改了,可是全部功能都是没有变化且一一对应的,做者的 commit 里使用的 badge 也是 refactor

钩子函数重构的 commit

图:钩子函数重构的 commit

3.x 钩子函数文档

图:3.x 钩子函数文档

4.x 钩子函数文档

图:4.x 钩子函数文档

4.x 钩子函数文档

图:4.x 钩子函数文档

相关文章
相关标签/搜索