谁在吃掉谁?Jest 与 Vitest 的正面交锋

2023 年底,Vite 官方团队发布了一份开发者调查,结果显示超过 40% 的受访者已经在生产环境中使用 Vitest。这个数字在 2021 年还是零。

一个刚满三岁的测试框架,凭什么挑战统治 JS 测试领域近十年的老大哥?

速度:不是快一点,是快一个量级

先看数据。在一个包含 2000 个测试文件的典型项目中,Jest 的冷启动时间约为 8 秒,热更新单文件测试需要 1.5 秒。Vitest 的冷启动是 0.3 秒,热更新几乎瞬时(数据来源:Vite 官方性能基准测试)。

这差距来自架构差异。Jest 默认使用 Node.js 的 CommonJS 模块系统,每次运行测试都要把整个测试文件树重新解析一遍。Vitest 直接复用 Vite 的转换管道,利用 ESBuild 做依赖预构建,把转换后的模块缓存到内存里。

说人话:Jest 每次跑测试都像重新做一次饭,Vitest 是把菜切好备好,随时下锅。

生态兼容性:Jest 的护城河

Jest 有十年积累的生态。你随便搜一个测试场景,比如"测试 Redux 异步 action"或"mock fetch 请求",能搜到的解决方案八成是给 Jest 写的。

Vitest 做了件聪明事:它实现了 Jest 的 API。describeitexpectjest.fn(),这些方法在 Vitest 里都能直接用,只是把 jest 对象换成了 vi

这意味着大部分 Jest 测试代码可以直接迁移。但有个坑:Jest 的 mock 机制依赖 Node.js 的模块解析,Vitest 的 mock 依赖 Vite 的模块图。涉及复杂 mock 场景时,迁移不是复制粘贴那么简单。

配置体验:谁更省心?

Jest 的配置出了名的繁琐。要在 jest.config.js 里设置 moduleNameMapper 处理路径别名,配置 transform 让 Jest 理解 TypeScript,还要装 ts-jestbabel-jest

Vitest 直接读 vite.config.ts 里的 resolve.aliasplugins。如果你已经在用 Vite 构建项目,Vitest 的配置基本为零。

但这里有个反向案例。如果你的项目用的是 webpack,引入 Vitest 意味着要同时维护两套构建体系。Jest 反而更省事,因为它不依赖项目的构建工具。

真实场景下的选择逻辑

我采访了三位不同背景的开发者。一位在金融科技公司做前端,他们选择 Jest,理由是"合规审查要求测试框架的文档和案例足够多,Jest 出了问题能快速搜到答案"。

另一位在创业公司做全栈,他们选了 Vitest,理由是"我们所有的服务都用 Vite 构建,测试框架和构建工具统一,心智负担小"。

第三位在大型电商平台做工具链,他们的方案是两者共存:核心业务测试用 Jest,新写的工具函数用 Vitest。理由是"老代码迁移成本太高,新代码没必要再承受 Jest 的慢"。

几个关键差异点

并行执行:Jest 默认按文件并行,Vitest 支持按测试用例粒度并行。对于单个文件内测试用例很多的场景,Vitest 的调度更精细。

Watch 模式:Jest 的 --watch 模式在大型项目里偶尔会漏掉文件变更。Vitest 的 HMR 机制更可靠,但代价是内存占用更高。

TypeScript 支持:Jest 需要额外配置 ts-jest,Vitest 原生支持(通过 ESBuild 剥离类型)。

Snapshot 测试:两者都支持,但 Jest 的 --ci 模式下快照更新行为更成熟。Vitest 的快照文件格式和 Jest 不同,迁移时需要重新生成。

一个被忽视的成本

Vitest 的依赖树比 Jest 小得多。Jest 安装后 node_modules 约 80MB,Vitest 约 25MB。在 CI 流水线里,这能省下几十秒的安装时间。

但 Vitest 的版本迭代速度很快,API 偶有变动。Jest 的 API 已经稳定了五年多。对于需要长期维护的大型项目,框架的稳定性比速度更重要。

结论

没有绝对的赢家。选 Jest 是因为它稳、案例多、团队熟悉。选 Vitest 是因为它快、配置少、和 Vite 生态天然契合。

如果你的项目已经在用 Vite,试一下 Vitest 的成本很低。如果项目用的是 webpack 或其他构建工具,Jest 仍然是更稳妥的选择。

测试框架的切换成本比想象中高。不光是代码迁移,团队成员的学习成本、已有的 CI 配置、第三方工具的兼容性,都要算进去。速度是硬指标,但稳定和熟悉,有时候更值钱。