WEBPACK多入口SSR热更新速度优化
一、背景&现状
1.在22年下半年时,针对vue开发时热更新慢(包括CSR和SSR)的问题,专门做过一次性能优化,发布@**********版本,牛客所有项目热更性能平均提升90%左右。
2.22年优化完成后,主站陆续有同学反馈,在开启SSR热更时开发依然很慢(热更时间长达10min),我将本地项目切换到@ncfe/nc.webpack2.x版本后,对比了2.x版本和3.x版本,在使用时3.x版本SSR性能提升明显。我将反馈热更慢的同学(姜同学)电脑重启后,发现CSR+SSR全量热更时间仅5S,怀疑是一线同学长期不重启Mac,Mac本身的内存管理问题。
HMR Time compare add/delete: <div>guoxianyue23333</div> | @ncfe/nc.webpack2.x.x(latest) | @ncfe/nc.webpack3.x.x(修复之前的最新版) |
CSR | 42S | 7S |
SSR | 41S | 7S |
3.后来由贺同学发现,当一线研发同学长期不关闭电脑时,服务终端进程中会针对不同的SSR页面(每个SSR页面由一个单独的JSON文件生成,同时每个JSON文件都由单独的webpack实例生成)生成多个webpack实例,且不会自动销毁。
4.通过观察发现,每次源码有改动,终端进程中的所有实例都会同时启动编译,由此定位到问题原因为一线同学长时间开发使用后,终端进程中存在的webpack编译实例过多导致的热更新变慢,也与前面我发现我自己本地热更不慢(没有长时间做主站业务开发)而主站一线同学反馈热更慢(长时间做主站业务开发)现象一致。
二、行业实践
此问题业务性较强,没有在网上看到相关问题和解决方案。
三、实现路径
1.问题发现
通过debug本地的webpack工程代码,发现主站工程最多同时存在21个入口,算上CSR实例,终端中最多会同时存在22个webpack实例。
2.针对此问题,共尝试了三种解决方法
方案一、魔改vue-server-render-plugin,使其支持多入口,从而使一个webpack实例就能处理21个入口,也就是说在这个方案下,node进程中永远只会有2个webpack实例,一个CSR webpack实例,一个SSR webpack实例。但是在此方案时,发现热更时间依然在16S左右,对业务来说依然不可接受。
方案二、使用parallel-webpack多线程webpack插件,在项目启动时,利用node多线程能力,每个线程启动一个webpack实例。但是使用这个方案时发现,每个webpack进程之间会相互等待,同时编译完成的时间在20S左右,对业务来说不可以接受。
方案三、一个思路,如果webpack热更慢是因为进程中的webpack实例过多,那么是不是可以通过某种方式进行实例管理来阻止node中的webpack实例逐渐增多?
基于以上思路,查找webpack文档时,没有发现webpack提供了关闭webpack实例的api。
通过debug webpack代码运行过程,发现webpack在启动watch之后,会返回一个实例,实例上存在close方法。
调用此方法,确实能将webpack实例关闭。那么现在的问题就是,通过什么方式管理内存中的webpack实例了,通过一些经典算法可以知道,LRU就是做这件事的,那么我们引入LRU算法,对进程中最活跃的3个SSR实例进行保活。
核心的SSR实例管理的LRU算法实现
四、业务接入流程
对于大部分业务来说是无感接入,部分锁定了我司通用打包脚本版本的项目,手动升级之后可用。
五、解决方案成果
接入此方案后,经过一线业务同学试用,前端研发同学的本地热更时间持续维持在8S左右,不再出现随着使用时间变长而出现本地热更变慢问题。
#webpack##前端打包##vue##SSR##前端热更新#