Vitest 切分支后 glob 仍含旧文件,检查带类型参数的模块缓存
import.meta.glob 带泛型时可能绕过缓存排除,旧转换结果继续引用已删除文件或漏掉新文件。按 Vitest 主版本使用正确缓存选项。
切换分支后,Vitest 仍导入已经删除的文件;新增匹配文件也没有进入 import.meta.glob 结果。若模块启用了文件系统转换缓存,并使用 import.meta.glob<unknown>(...) 这样的类型参数,检查是否复用了旧的文件列表。
这一具体路径在 Vitest 4.1.11 中出现,已核对的 5.0.5 正式缓存代码也只用字符串 import.meta.glob( 判断是否跳过缓存。紧跟泛型的 < 让这条检查失效;模块自身源码没有变化,即使 glob 匹配的目录成员已经改变,旧转换仍可能被复用。
const files = import.meta.glob<unknown>('./src/*.js', { eager: true });
上面是调用形状示例。它本来就会在转换时展开匹配文件,不是运行时随时扫描文件系统;问题是后一次测试转换应重新看到当前检出的成员,却拿到了前一次结果。
用文件增删区分缓存与模式错误
先保留实际 Vitest、Vite 版本、缓存配置、glob 表达式及匹配文件清单。确认新文件的目录、扩展名与大小写确实匹配;模式只覆盖一层目录时,深层文件本来就不会出现。
比较关闭缓存后的同一条测试。如果结果恢复为当前文件集合,才继续沿模块缓存诊断。不要把缺少源码文件误当缓存问题,也不要用重新创建空文件掩盖错误导入。
5 系列可先明确停用文件转换缓存
Vitest 5.0.5 使用顶层 test 缓存选项,临时配置为:
import { defineConfig } from 'vitest/config';
export default defineConfig({
test: {
fsModuleCache: false,
},
});
保留项目其他选项。关闭后每次进程可能需要重新转换更多模块,运行时间会增加,但无需为了这个问题删除锁文件或共享包缓存。Vitest 4.1 的相应选项仍在 experimental 下,不能把 5 系列配置不加核对地复制回旧版本。
需要保留缓存时,可以按实际版本的插件 API 对含 glob 的模块返回“不缓存”,但 4 与 5 的 API 名称有变化,应使用对应正式文档。只删除泛型虽然可能命中字面量检查,却可能损失类型约束,而且换行、空格或转换器生成的 glob 仍有其他边界;不宜把它当通用修复。
验收要跨两个独立测试进程
先以当前成员运行一次,再添加一个匹配文件,启动新进程确认它进入结果;随后移除或切走该文件,再运行,确认没有旧导入残留。也要检查原来不匹配的文件仍被排除,以及 eager 模块的导出与副作用没有改变。
后续采用正式修复时保留这组增删检查,再恢复缓存并观察连续运行。仅在同一个 watch 进程里通过,或只清一次缓存通过,都没有覆盖跨进程、跨分支复用的条件。回退缓存策略时恢复原配置,避免 CI 继续上传另一条路径的旧缓存。


