Vitest 配置完全指南:从 vite.config 到 vitest.config 的优先级、合并与最佳实践
【免费下载链接】vitestNext generation testing framework powered by Vite.项目地址: https://gitcode.com/GitHub_Trending/vi/vitest
本篇指南以 Vitest 官方配置文档为核心,系统讲解 Vitest 配置文件的选择逻辑、查找顺序、优先级规则,以及configDefaults、mergeConfig、--config、VITEST环境变量等关键配置手段的底层实现。读完本文,你将能够根据项目实际情况(纯 Vite 应用、非 Vite 项目、多配置文件并存、配置以函数形式导出等)正确搭建 Vitest 配置,并学会利用仓库源码验证配置行为的真实机制。
配置文件的选择策略:Vitest 如何读取你的配置
Vitest 基于 Vite 构建,因此天然复用 Vite 的配置体系。如果你已经在使用 Vite 且存在vite.config文件,Vitest 会读取它,从而与 Vite 应用共享插件与 setup 配置。但测试环境与主应用往往需要不同的设置,此时 Vitest 提供三种方式让测试配置与主应用配置解耦:
- 创建
vitest.config.ts:它拥有更高优先级,会覆盖(override)vite.config.ts中的全部配置——即vite.config中的所有选项都会被忽略。Vitest 支持所有常规 JS/TS 扩展名,但不支持json。 - 通过 CLI 传入
--config选项,例如vitest --config ./path/to/vitest.config.ts,显式指定配置文件的绝对或相对路径。 - 在
vite.config.ts内利用process.env.VITEST或defineConfig的mode属性做条件配置:mode在不被--mode覆盖时会被设置为test。注意,与任何环境变量一样,VITEST在测试中也会暴露到import.meta.env上。
配置文件的查找顺序(源码级验证)
当没有显式传入--config时,Vitest 会在项目root目录下按以下顺序查找配置文件:
- 先查找
vitest.config.{ts,mts,cts,js,mjs,cjs} - 再查找
vite.config.{ts,mts,cts,js,mjs,cjs} - 若两者都不存在,Vitest 将在无配置文件的情况下运行
这一查找逻辑与源码中的定义完全一致。在 constants.ts 中,配置文件名称与扩展名被显式枚举:
const CONFIG_NAMES: string[] = ['vitest.config', 'vite.config'] const CONFIG_EXTENSIONS: string[] = ['.ts', '.mts', '.cts', '.js', '.mjs', '.cjs'] export const configFiles: string[] = CONFIG_NAMES.flatMap(name => CONFIG_EXTENSIONS.map(ext => name + ext), )而实际的查找过程在 resolveConfig.ts 的findConfigFile中实现——它严格按顺序遍历上述configFiles列表,命中第一个存在的文件即返回:
export function findConfigFile(root: string): string | false { for (const configFile of configFiles) { const configPath = resolve(root, configFile) if (existsSync(configPath)) { return configPath } } // if not found, then there is no config to find. // `false` will stop vite from trying to find it again return false }从源码可以推断:vitest.config.*之所以能"覆盖"vite.config.*,正是因为它在查找列表中排在前面——一旦命中,vite.config.*就永远不会被读取,从而表现为后者的全部选项被忽略。
为配置启用类型提示:test属性与 TypeScript 引用
要配置 Vitest 自身,需要在 Vite 配置中加入test属性。如果defineConfig是从vite本身导入的,则需要在配置文件顶部添加 triple slash 指令 来引入 Vitest 的类型声明。
如果你不使用 Vite,则从vitest/config导入defineConfig:
import { defineConfig } from 'vitest/config' export default defineConfig({ test: { // ... 在此处指定选项。 }, })如果你已有 Vite 配置,可以通过/// <reference types="vitest/config" />引入test的类型:
/// <reference types="vitest/config" /> import { defineConfig } from 'vite' export default defineConfig({ test: { // ... 在此处指定选项。 }, })两条路径在源码层面是等价的:从 public/config.ts 可以看到,mergeConfig直接 re-export 自vite,defineConfig接受的也正是ViteUserConfig类型(含test扩展字段)。因此无论defineConfig来自哪里,最终产出的都是一个兼容 Vite 的配置对象。
基于默认值扩展:configDefaults
Vitest 暴露了默认配置对象configDefaults,方便你在其基础上展开(spread)并追加自定义项:
import { configDefaults, defineConfig } from 'vitest/config' export default defineConfig({ test: { exclude: [...configDefaults.exclude, 'packages/template/*'], }, })configDefaults的定义位于 defaults.ts,并经过Object.freeze冻结,保证不可被意外篡改。它包含了大量关键默认值,了解它们有助于你判断何时需要覆盖:
| 选项 | 默认值 | 说明 |
|---|---|---|
include | ['**/*.{test,spec}.?(c|m)[jt]s?(x)'] | 测试文件匹配模式 |
exclude | ['**/node_modules/**', '**/.git/**'] | 默认排除目录 |
environment | 'node' | 默认运行环境 |
globals | false | 是否注入全局 API |
watch | !isCI && process.stdin.isTTY && !isAgent | 是否默认启用监听模式 |
allowOnly | !isCI | 是否允许.only |
clearMocks | true | 测试间是否自动清理 mock |
restoreMocks/mockReset | false | 是否自动恢复/重置 mock |
teardownTimeout | 10000 | teardown 超时(毫秒) |
maxConcurrency | 5 | 最大并发数 |
update | false | 是否默认更新快照 |
reporters | ['default'](CI/Agent 下为minimal,GITHUB_ACTIONS 时追加github-actions) | 默认报告器 |
fakeTimers | { loopLimit: 10_000, shouldClearNativeTimers: true } | 假定时器默认行为 |
typecheck.checker | 'tsc' | 类型检查器 |
slowTestThreshold | 300 | 慢测试阈值(毫秒) |
该默认对象在 resolveConfig.ts 中通过deepMerge({}, configDefaults, options)与用户配置合并,因此你在test中未指定的选项都会自动回落到上表中的默认值。
合并多个配置文件:mergeConfig
当使用独立的vitest.config.js时,如果你仍想继承另一个配置文件(例如vite.config)中的 Vite 选项,可以使用mergeConfig进行深度合并:
import { defineConfig, mergeConfig } from 'vitest/config' import viteConfig from './vite.config' export default mergeConfig(viteConfig, defineConfig({ test: { exclude: ['packages/template/*'], }, }))注意此处的语义:mergeConfig(viteConfig, vitestConfig)会将两个配置对象深度合并,test等 Vitest 专属选项来自第二个参数,而 Vite 通用选项(插件、别名等)来自第一个参数,从而实现在复用 Vite 配置的同时覆盖测试相关选项。
配置以函数形式导出时
如果 Vite 配置是以函数形式导出的(以便接收configEnv环境信息),你可以这样组合:
import { defineConfig, mergeConfig } from 'vitest/config' import viteConfig from './vite.config' export default defineConfig(configEnv => mergeConfig( viteConfig(configEnv), defineConfig({ test: { exclude: ['packages/template/*'], }, }) ))这里viteConfig(configEnv)先被调用以生成实际配置对象,再与测试配置合并,确保函数形式的配置同样能够正常参与合并。mergeConfig从vite中 re-export(见 public/config.ts),因此其合并行为与 Vite 自身的配置合并完全一致。
复用 Vite 的全部配置能力
由于 Vitest 使用 Vite 配置,你可以在顶层(而非test属性内)直接使用 Vite 的任何配置选项。例如:
define:定义全局变量resolve.alias:配置路径别名- 以及
plugins、server、resolve等一切 Vite 支持的能力
这些选项应定义在配置对象的顶层,而不是嵌套在test属性内部——test属性只负责 Vitest 专属的测试选项。
自动依赖安装与VITEST_SKIP_INSTALL_CHECKS
Vitest 在检测到某些必要依赖未安装时,会提示你进行安装。如果你希望禁用这一行为,可以设置环境变量:
VITEST_SKIP_INSTALL_CHECKS=1这一机制的实现位于 packageInstaller.ts。ensureInstalled首先检查VITEST_SKIP_INSTALL_CHECKS,一旦设置则直接跳过全部检查返回true;随后它通过isPackageExists检测依赖是否可用,若缺失则在 TTY 终端中弹出交互式确认(prompts),用户确认后调用@antfu/install-pkg以dev: true方式安装依赖,并提示"安装完成,请重新运行命令"。若运行环境不是 TTY(如 CI),则不会弹出提示,直接返回false。因此:
- 在 CI / 非交互环境中,未安装的依赖不会被自动安装,Vitest 会以 "MISSING DEPENDENCY" 标签提示缺失;
- 在本地交互终端中,你可以选择一键安装后再重新运行。
在 CI 管道中显式设置VITEST_SKIP_INSTALL_CHECKS=1是一种常见的确定性做法,可避免意外的交互等待。
配置选项与项目(Projects)的限制
所有配置选项的完整列表可参阅 config 目录 下的各选项页面。其中需要注意:部分选项在 project 配置中不受支持,文档中以 图标标记,这类选项只能在根级(root)Vitest 配置中设置,而不能在子项目(project)配置内覆盖。
从实现角度看,这一限制与配置的解析链路相关:根配置会通过findConfigFile在项目 root 下被加载,并通过deepMerge({}, configDefaults, options)得到完整默认值(resolveConfig.ts),而子项目配置只允许覆盖其中被允许的字段。涉及include、exclude等高频选项时,建议先在根配置确认默认值,再决定是在根级还是项目级覆盖,避免出现"配置不生效"的困惑。
实战要点速查
- 纯 Vite 项目:直接在
vite.config.ts中添加test属性 +/// <reference types="vitest/config" />,与主应用共享插件。 - 非 Vite 项目 / 需要独立测试配置:创建
vitest.config.ts,从vitest/config导入defineConfig,此时vite.config.ts会被完全忽略。 - 同时保留两套配置:在
vitest.config.ts中用mergeConfig(viteConfig, defineConfig({ test: {...} }))继承 Vite 配置;若 Vite 配置是函数,先调用再合并。 - 只想微调默认行为:使用
configDefaults.exclude等展开默认数组,而非硬编码完整列表。 - CI 环境:设置
VITEST_SKIP_INSTALL_CHECKS=1并配合--config显式指定配置文件,保证行为可复现。 - 条件切换:在
vite.config.ts中根据process.env.VITEST或mode === 'test'动态切换配置分支。 - 配置文件查找:记住顺序
vitest.config.*优先于vite.config.*,支持.ts/.mts/.cts/.js/.mjs/.cjs六种扩展名,但不支持json。
通过结合 defaults.ts、constants.ts、resolveConfig.ts 与 packageInstaller.ts 的源码,你可以准确预测 Vitest 在任意目录结构下的配置文件解析结果,从而为不同规模的项目设计出既清晰又不易出错的测试配置方案。
【免费下载链接】vitestNext generation testing framework powered by Vite.项目地址: https://gitcode.com/GitHub_Trending/vi/vitest
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考