
Strapi 共享 Vitest 配置包 vitest-configunitPreset 原理与 Jest 到 Vitest 的渐进式迁移实践【免费下载链接】strapi Strapi is the leading open-source headless CMS. It’s 100% JavaScript/TypeScript, fully customizable, and developer-first.项目地址: https://gitcode.com/GitHub_Trending/st/strapiStrapi 官方仓库正在用 Vitest 逐步接管后端单元测试而packages/utils/vitest-config就是支撑这一迁移的私有共享配置包。本篇以该包的 README 及其预设源码为骨架完整讲解unitPreset每一项参数的含义、各包接入该预设的标准姿势以及 Strapi 如何通过.vitest.test.ts命名约定让 Jest 与 Vitest 两套测试框架在同一 monorepo 中互不干扰地并存运行。一、包定位一个明确不对外发布的内部工具包vitest-config的定义非常克制。从其 package.json 可以确认以下事实包名为vitest-configprivate: true版本5.52.2与 monorepo 其余包保持同步的版本策略对外仅暴露一个入口./presets/unit同时映射类型与实现到./src/presets/unit.tspeerDependencies要求使用方必须自行安装vitest ^4.0.0配置包本身不锁定具体运行时版本devDependencies 中通过vitest: catalog:引用仓库统一的 Yarn catalog 版本engines约束为 Node.js20.0.0 26.x.x、npm6.0.0与仓库根 package.json 的全局 engines 约束一致。README 开头用 IMPORTANT 提示框明确声明这是一个私有包不打算被 Strapi monorepo 之外的用户使用。因此下文所有用法都应以“在 Strapi 仓库内接入新测试”为适用前提外部项目参考其思路时应自行落地等价配置。二、unitPreset 源码逐项解析预设的完整实现只有 32 行位于 src/presets/unit.ts通过defineConfig导出为unitPresetimport { defineConfig } from vitest/config; export const unitPreset defineConfig({ test: { // Require explicit imports from vitest (no globals) globals: false, // Node environment for backend unit tests environment: node, // Only run tests with .vitest.test.ts suffix for incremental migration include: [**/*.vitest.test.ts], // Exclude common non-test files and directories exclude: [ **/node_modules/**, **/dist/**, **/.cache/**, **/*.testdata.{js,ts}, **/*.test.utils.{js,ts}, **/*.d.ts, **/__tests__/resources/**, **/tests/resources/**, ], // Match Jests default timeout testTimeout: 5000, // Watch mode settings watch: false, }, });逐项说明其设计意图参数取值作用与设计考量globalsfalse禁用 Vitest 全局注入强制测试文件显式import { describe, it, expect } from vitest。好处是依赖关系在文件层面可见、易被静态检查发现environmentnode该预设服务于后端单元测试server 侧代码运行在 Node 环境而非 jsdominclude[**/*.vitest.test.ts]这是渐进式迁移的关键只收集带.vitest.test.ts后缀的测试文件源码注释也写明是 for incremental migration。普通*.test.ts文件仍归 Jest 管辖两套框架按文件后缀自动分流exclude8 条 glob排除node_modules、dist、.cache、类型声明文件*.d.ts以及两类“看起来像测试但并非测试”的文件*.testdata.{js,ts}测试数据与*.test.utils.{js,ts}测试工具函数同时排除__tests__/resources/与tests/resources/资源目录testTimeout5000源码注释明确写着 Match Jests default timeout——刻意对齐 Jest 的默认 5 秒超时避免迁移到 Vitest 后原有测试因超时行为变化而失败watchfalse预设层面默认关闭 watch保证 CI 等场景下的确定行为需要监听模式时由上层脚本显式开启见第四节值得注意的是exclude列表中的*.testdata.{js,ts}、*.test.utils.{js,ts}、__tests__/resources等规则与 Jest 侧的忽略规则见下文jest-preset.unit.js几乎一一对应可以推断这套预设是在把既有 Jest 的过滤口径平移到 Vitest 上从而保证同一批“伪测试文件”在两套框架下都不被误收集。该包的 tsconfig.json 继承自 packages/utils/tsconfig/base.json仅声明types: [node]并包含src目录说明预设本身是纯 TypeScript 源码导出不做独立构建。三、标准接入姿势mergeConfig 合并预设README 给出的 Usage 示例也是全仓库 16 个包实际采用的统一模板import { defineConfig, mergeConfig } from vitest/config; import { unitPreset } from vitest-config/presets/unit; export default mergeConfig( unitPreset, defineConfig({ test: { root: __dirname, }, }) );要点拆解导入路径是子路径导出vitest-config/presets/unit对应package.json的exports字段包名没有strapi/前缀是因为它属于内部工具包AGENTS.md 将packages/utils/描述为 Shared tooling: logger, eslint-config, tsconfig, vitest-config。mergeConfig(unitPreset, defineConfig(...))的顺序共享预设在前包级覆盖在后。后一个配置中出现的同名字段会覆盖预设值。包级仅需补充root: __dirname把测试根目录锚定到各包自身目录使每个包的vitest.config.ts成为相互独立的测试工程互不串扰。仓库中已经落地该模板的配置文件均与 README 示例逐字一致例如 packages/core/utils/vitest.config.ts、packages/core/database/vitest.config.ts、packages/providers/upload-local/vitest.config.ts、packages/plugins/sentry/vitest.config.ts 等全文如下以 database 包为例import { defineConfig, mergeConfig } from vitest/config; import { unitPreset } from vitest-config/presets/unit; export default mergeConfig( unitPreset, defineConfig({ test: { root: __dirname, }, }) );当前仓库中接入vitest-config/presets/unit的包共 16 个覆盖核心层、Provider 层与插件层核心包packages/core/core/vitest.config.ts、packages/core/database/vitest.config.ts、packages/core/utils/vitest.config.ts、packages/core/permissions/vitest.config.ts、packages/core/data-transfer/vitest.config.ts、packages/core/content-type-builder/vitest.config.tsCLI 包packages/cli/cloud/vitest.config.tsProvider 包packages/providers/email-amazon-ses/vitest.config.ts、packages/providers/email-mailgun/vitest.config.ts、packages/providers/email-nodemailer/vitest.config.ts、packages/providers/email-sendmail/vitest.config.ts、packages/providers/upload-aws-s3/vitest.config.ts、packages/providers/upload-local/vitest.config.ts插件包packages/plugins/color-picker/vitest.config.ts、packages/plugins/sentry/vitest.config.ts每个接入包的 package.json 还会声明对vitest-config的精确版本依赖如vitest-config: 5.52.2与vitest: catalog:并在其tsconfig.json的include中加入vitest.config.ts例如 packages/core/core/tsconfig.json保证配置文件本身也纳入类型检查。四、运行入口根工程级 projects 模式与包级脚本monorepo 根目录的 vitest.config.ts 只有 7 行import { defineConfig } from vitest/config; export default defineConfig({ test: { projects: [packages/**/vitest*.config.*], }, });这里使用 Vitest 的projects多工程模式通过 glob 一次性发现packages/下所有vitest*.config.*文件把 16 个包级配置聚合成一次运行。对应根 package.json 的两条脚本test:unit:vitest: vitest run, test:unit:vitest:watch: vitest --watch一次性执行CI 友好yarn test:unit:vitest即vitest run此时预设中watch: false的默认值与一次性运行语义一致本地开发监听yarn test:unit:vitest:watch即vitest --watch用命令行标志显式覆盖预设里的watch: false这解释了预设为什么要显式写死watch: false——它是run与--watch两种入口的公共基线。包级别同样提供对称脚本见 packages/cli/cloud/package.jsontest:unit:vitest与test:unit:vitest:watch允许单独对某一个包的 Vitest 用例做开发迭代。五、渐进式迁移机制后缀约定让 Jest 与 Vitest 并存unitPreset中include: [**/*.vitest.test.ts]并非孤立的命名偏好它与 Jest 侧配置构成一对镜像约束共同实现“按文件逐个迁移、两套框架零冲突”Vitest 侧include只认.vitest.test.ts后缀Jest 存量测试文件*.test.ts、__tests__/*等对 Vitest 完全不可见Jest 侧仓库根的 jest-preset.unit.js 在testPathIgnorePatterns中显式加入了.vitest.test.ts源码注释写着 Prevent Jest from running Vitest test files防止 Jest 误跑新框架的测试同时modulePathIgnorePatterns、testMatch等规则维持原有 Jest 口径命名约定迁移一个测试文件时只需把文件名从xxx.test.ts重命名为xxx.vitest.test.ts并将describe/it/expect改为从vitest显式导入因为预设强制globals: false该文件便自动从 Jest 流水线切换到 Vitest 流水线其余文件不受影响。从源码结构看这套约定目前已在 43 个测试文件中落地分布于 packages/core/database/src/fields/tests/string.vitest.test.ts、packages/core/content-type-builder/server/src/services/schema-builder/tests/content-type-builder.vitest.test.ts、packages/cli/cloud/src/create-project/utils/tests/get-project-name-from-pkg.vitest.test.ts 等位置均保持“源码旁__tests__目录”的既有组织方式与 Jest 测试同目录共存。这种“后缀即路由”的方案对大型 monorepo 的测试框架换代尤其实用迁移粒度细化到单个文件任何一步都可以随时停下而不是一次性改写全仓库。六、适用前提与使用边界小结版本前提vitest ^4.0.0peer 依赖Node.js20.0.0 26.x.x仓库统一通过 Yarn 4packageManager: yarn4.12.0的 workspace 与 catalog 机制管理依赖。范围边界该包为私有内部包仅暴露./presets/unit一个子路径README 明确声明不建议在 Strapi monorepo 之外使用。预设语义边界unitPreset面向后端 Node 单元测试仓库中前端单元测试仍走 Jest front 预设体系二者不要混用。可复制要点即便不能直接安装该包仓库外的项目也可以照搬其三个核心手法——共享预设 mergeConfig包级覆盖、testTimeout对齐旧框架默认值、以文件后缀约定实现测试框架的渐进式共存。【免费下载链接】strapi Strapi is the leading open-source headless CMS. It’s 100% JavaScript/TypeScript, fully customizable, and developer-first.项目地址: https://gitcode.com/GitHub_Trending/st/strapi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考