Vitest 在使用过程中,最让人头疼的问题往往集中在:隐式规则太多,导致测试环境下的构建结果与常规构建不一致。最终结果就是——你明明写对了代码,测试却无法通过,或者通过了但心里没底。下面列举的几个常见坑,几乎每个从 Vue 3 项目迁移过来的团队都会踩上一次。

1. 插件 transform 无效
费了好大功夫写了一个 Vite 插件,结果在 Vitest 里运行毫无反应。怎么回事?经过排查发现,Vitest 默认不会处理公共库(node_modules 中的依赖)。如果你的插件需要对某个公共库进行 transform,必须手动配置 test.server.deps.inline,明确告诉它“这个库不要跳过,请给我处理”。这个配置项隐藏得比较深,很容易被忽略。
2. 模块被解析为 CommonJS 版本
原本以为 CommonJS 版本也能用,反正 Node 环境运行没问题。但问题在于,测试的目的是模拟真实的浏览器环境。比如你想验证代码在关闭 __VUE_OPTIONS_API__ 的情况下是否正常工作,而 Vue 的 CommonJS 预构建产物根本没有这个开关,测试虽然能通过,却无法证明任何事。解决方法其实不复杂:通过插件提前按照浏览器规则去解析模块。这里推荐使用 @rollup/plugin-node-resolve,并设置 browser: true。注意还要调整钩子执行顺序,确保它在 Vite 内置插件之前执行:
(function() {
let plugin = nodeResolve({browser: true });
plugin.resolveId.order = undefined; // 调整钩子执行顺序
plugin.enforce = "pre"; // 确保在 Vite 内部插件之前执行
return plugin;
})()
3. tsx 配置失效
明明在 tsconfig.json 里配置好了 TypeScript 编译选项,但最终产物却与预期不符。追查了半天,发现罪魁祸首是 @vitejs/plugin-vue-jsx 这个插件——它内置了一套基于 Babel 的 TypeScript 编译配置,根本不读取你的 tsconfig。理想的方案是让前面的流程先把 TSX 转成 JSX,然后这个插件只处理 JSX 部分,各司其职。配置修改如下:
(function() {
let plugin = vueJsx({
tsTransform: 'built-in',
include: /\.(j|t)sx$/
});
plugin.transform.order = undefined;
plugin.enforce = "pre"; // 确保提前拦截和处理
return plugin;
})()
这三个坑,核心都是 Vitest 的隐式规则所导致的。搞清楚背后的原理,配置起来就不再是玄学。希望这些经验能帮你少走弯路。
