Unot

码 · webpack5 下开发时的重复编译

该项目开发周期持续了三至四年,随着需求迭代规模的不断壮大,到我参与其中时,src 目录下的源码文件已至六千余个。

1710913681689.jpg

冷启动(5min),热更新(4-5s)的速度可见缓慢,对日常开发效率造成了极大的影响。(插一句题外话,在此等量级的项目上还能保持这个速度已经是难能可贵了)。

项目最初是默认使用 Vue CLI 进行构建,由于业务复杂,导致该项目的自定义构建配置极多,都塞在 vue.config.js 文件中使用链式 API 的方式定义,可读性、可维护性较差。

改造的选型有 Vite、webpack5,最终还是选用了 webpack5。至于为什么选择 webpack5,我们之后再叙。

在改造的过程中,遇到了一个比较少见生僻的问题。

在工作设备上,使用 WebStorm 上进行开发时,一次保存会触发多次构建,大多数情况下表现为两次,而 VSCode 上则正常。

我们知道,为了支持代码关系重构、类型推荐、跨文件跳转等功能,WS 启动时会先对项目代码先分析一遍建立缓存索引。

而 Webpack5 的核心升级也是引入了本地持久化缓存,在这里也是有开启缓存支持,因此我们开发时的每次保存,都会触发缓存的更新,

其间我甚至 inspect 了 Vue CLI 的原始配置文件查看它的全部 webpack 配置,然而并没有发现有特殊的配置之处。由于变数太多,无法使用排除法一步步缩小范围。

之后也没有在互联网及有关的 webpack github issue 下找到相关回答,我有了以下猜想:

  1. 在每次保存时,WS 的 内部保存机制 不同于 VSCode 直接对文件进行修改,导致 WS 并不会立即修改真正的文件,而是先同步缓存,再将缓存更新到要修改的文件上去。

  2. 由于 WS 在文件修改保存后所要做的工作较多,缓存开始改变到整个缓存更新结束,不是在极短时间内完成的(这个点与我们工作设备的硬盘性能参数落后也有关系,导致在极短时间内有大量数据写入硬盘,但被硬盘 IO 所限制),从而引发了多次编译。

可以看到,由于项目规模过大,使用持久化缓存产生的缓存文件大小都足足有 1.6G 左右。

1710906631368.jpg

综合来看,是由一次保存触发的多次编译,大概率是由这一次的保存反复修改了文件所引发的。

在我将所有关于 WS 保存后能够修改文件的额外配置取消后,问题依旧。

那么解决的思路就由既然无法阻止 WS 反复修改文件,变为将短时间内的多次修改只触发一次编译。

于是乎,我在 webpack5 文档中找到了如下配置:

watchOptions.aggregateTimeout

该配置主要的作用为延迟构建,将指定时间内的多次更改都聚合在一次重新构建内。将之设置为 200ms 后,问题解决。


  // webpack.dev.js

  watchOptions: {
    ignored: /node_modules/,
    aggregateTimeout: 200
  }

可能很多人会说,那你不要用 WS 改用 VSCode 不就解决了嘛。

这便牵扯到了一个永恒的话题:哪个编辑器或者 IDE 好用。/(ㄒoㄒ)/~~

存在即合理,每一种工具都有其适用的价值所在,因人习惯而异,因项目规模、开发场景而异...

Thoughts? Leave a comment