DEBUG.WIKI
晚安云;香港 CN2 ¥15/月
PanstarCloud:部署应用,接入 AI,云服务器与 AI 网关
野草云;香港 200Mbps 峰值;不限月流量 · BGP VPS;查看套餐 →

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 继续上传另一条路径的旧缓存。