ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

在 Create React App 项目中使用独立 jest.config.js:CRACO createJestConfig 实战指南

在 Create React App 项目中使用独立 jest.config.js:CRACO createJestConfig 实战指南 开发工具前端构建【免费下载链接】cracoCreate React App Configuration Override, an easy and comprehensible configuration layer for Create React App.项目地址https://gitcode.com/gh_mirrors/cr/craco点击查看免费下载导读本指南讲解如何在基于 Create React AppCRA的项目中借助 CRACOCreate React App Configuration Override提供的createJestConfigAPI把 CRACO 的 Jest 配置合并结果导出为一个独立的jest.config.js文件。这样你就可以让编辑器、IDE 以及直接调用的 Jest CLI 都读到同一份完整配置同时保留 CRACO 的jest.configure与jest.babel配置能力。读完本文你将掌握createJestConfig的用法、它与craco test脚本模式的区别以及合并过程背后的源码级工作原理。为什么需要独立的 jest.config.jsCRA 的react-scripts test脚本内部会通过react-scripts/utils/createJestConfig.js动态生成 Jest 配置这份配置默认只存在于脚本运行时并不落盘。因此当你使用 VS Code、JetBrains 等编辑器的 Jest 集成或者直接在命令行运行jest时它们找不到一份可以读取的jest.config.js也就无法获得完整的模块映射、transform 与 globals 配置。CRACO 提供了一条出路通过createJestConfig(cracoConfig)把 CRACO 处理过的 Jest 配置物化成普通对象写入jest.config.js。这样编辑器 / IDE 的 Jest 插件可以正确识别并运行测试直接执行npx jest时配置行为与craco test一致生成的配置文件可以提交进版本库供团队统一使用。与此相对CLI 模式craco test是在进程内动态覆盖react-scripts的 Jest 配置提供者provider两者殊途同归但独立配置文件更适合工具链集成。两种方式的差异会在下文详细展开。完整配置示例原文档方案原文档给出的方案由两个文件组成craco.config.js声明你要注入的 Jest 配置jest.config.js负责调用createJestConfig生成最终配置。craco.config.jsmodule.exports { jest: { configure: { globals: { CONFIG: true, }, }, }, };jest.config.jsconst { createJestConfig } require(craco/craco); const cracoConfig require(./craco.config.js); const jestConfig createJestConfig(cracoConfig); module.exports jestConfig;这里的关键点createJestConfig由craco/craco从包入口直接导出见 packages/craco/src/index.ts 的导出列表它接受一个 CRACO 配置对象并返回JestConfig.InitialOptions类型的完整配置对象你在jest.configure中声明的globals.CONFIG: true会被深度合并进最终配置因此测试代码中可以通过global.CONFIG读取到该值。如果你更喜欢把路径别名、transform 等常用配置统一收进jest.configure也是同样的写法。例如在 test/unit/merging-tests/custom-jest-config/craco.config.js 中测试夹具就用configure同时注入了自定义transform与moduleNameMappermodule.exports { jest: { configure: { transform: { ^.\\.[t|j]sx?$: babel-jest, }, moduleNameMapper: { ^components/(.*)$: rootDir/src/components/$1, }, }, }, };对应的单元测试 test/unit/merging-tests/custom-jest-config/jest.test.js 断言了两件事自定义配置如moduleNameMapper的别名映射被正确应用且原有配置没有被移除最终配置的键数量不小于原始配置这正是深合并语义的体现。调用链解析createJestConfig 内部做了什么createJestConfig的实现位于 packages/craco/src/lib/features/jest/api.ts核心流程如下export function createJestConfig( callerCracoConfig: CracoConfig, callerContext: JestContext {}, options: CliArgs {} ): JestConfig.InitialOptions { // 1. 校验入参 if (!callerCracoConfig) { throw new Error(craco: cracoConfig is required.); } if (isFunction(callerCracoConfig)) { throw new Error(craco: cracoConfig should be an object.); } // 2. 保证 NODE_ENV 存在 if (!process.env.NODE_ENV) { process.env.NODE_ENV development; } // 3. 记录 CLI 参数与上下文 setArgs(options); const context: JestContext { env: process.env.NODE_ENV, ...callerContext, }; // 4. 处理 CRACO 配置含插件等并解析 CRA 的 paths const cracoConfig processCracoConfig(callerCracoConfig, context); context.paths getCraPaths(cracoConfig); // 5. 加载 react-scripts 自带的 createJestConfig provider const craJestConfigProvider loadJestConfigProvider(cracoConfig); // 6. 合并并返回最终配置 return mergeJestConfig(cracoConfig, craJestConfigProvider, context); }几个值得注意的实现事实入参必须是对象cracoConfig不允许是函数。如果你习惯把 CRACO 配置导出为函数异步配置这里会直接抛错这一点与 website/docs/configuration/jest.md 描述的jest.configure用法无关是createJestConfig自身的约束。NODE_ENV 兜底若环境变量未设置默认置为development并写入context.env。如果你的测试需要test环境请在调用前显式设置NODE_ENVtest或者依赖craco test脚本它会在 scripts/test.ts 中把NODE_ENV默认设为test。provider 来源loadJestConfigProvider会按cracoConfig.reactScriptsVersion ?? react-scripts解析utils/createJestConfig.js见 packages/craco/src/lib/cra.ts因此如果项目使用了自定义的 react-scripts 版本或 forkCRACO 依然能正确找到对应的 Jest 配置生成器。最终合并所有逻辑收敛到mergeJestConfig见 packages/craco/src/lib/features/jest/merge-jest-config.ts它负责 Babel 变换器覆盖、jest.configure合并以及插件应用。jest.configure 的两种形态对象合并与函数总控jest.configure可以是一个对象字面量也可以是一个函数这与 CRACO 全局的对象字面量 vs 函数约定一致详见 website/docs/configuration/getting-started.md。在源码层面这两种形态由giveTotalControlmerge-jest-config.ts分发处理function giveTotalControl( jestConfig: JestConfig.InitialOptions, configureJest: ConfigureJestConfig.InitialOptions, JestContext, context: JestContext ) { if (isFunction(configureJest)) { jestConfig configureJest(jestConfig, context); if (!jestConfig) { throw new Error( craco: jest.configure function didnt returned a Jest config object. ); } } else { // 对象字面量与原配置深合并 jestConfig deepMergeWithArray({}, jestConfig, configureJest); } return jestConfig; }对象字面量走deepMergeWithArray深合并数组按索引合并而非整体替换。这也解释了上一节测试用例中原有配置不被移除的行为。原文档示例中的globals: { CONFIG: true }就属于这一类globals对象会与 CRA 默认的 globals 逐键合并。函数接收 CRA 生成的原始jestConfig作为第一参数第二参数是上下文对象你完全掌控返回值如果忘记返回对象会抛出明确错误。适合需要对配置做条件化增删的场景。函数形态的完整示例module.exports { jest: { configure: (jestConfig, { env, paths, resolve, rootDir }) { // env: 当前 NODE_ENV // paths: CRA 解析出的路径集合appSrc、appBuild 等 // resolve: 用于按 reactScriptsVersion 解析相对模块 // rootDir: 项目根目录 if (env test) { jestConfig.testPathIgnorePatterns [/node_modules/]; } return jestConfig; }, }, };上下文对象env、paths、resolve、rootDir函数形态的上下文对象在 website/docs/configuration/jest.md 中有明确说明其中resolve与rootDir由 CRA 侧提供。结合 merge-jest-config.ts 的实现可以看到CRACO 在合并时构造了如下上下文const jestContext { ...context, resolve: customResolve, // 基于 reactScriptsVersion 的模块解析函数 rootDir: projectRoot, // 项目根目录与 CRA 的 paths 对应 };resolve(relativePath)在react-scripts或reactScriptsVersion指定的包下解析相对路径模块便于你引用 CRA 内部的工具或配置rootDir即projectRoot在写moduleNameMapper、coveragePathIgnorePatterns等含rootDir占位的配置时非常有用。jest.babel 与 Babel 变换器覆盖在jest.configure合并之前mergeJestConfig还会执行configureBabelmerge-jest-config.ts处理 website/docs/configuration/jest.md 中描述的jest.babel选项module.exports { jest: { babel: { addPresets: true /* 默认值 */, addPlugins: true /* 默认值 */, }, configure: { /* ... */ }, }, };jest.babel.addPresetsboolean true是否把cracoConfig.babel.presets追加到babel-jest变换器的 presets 中jest.babel.addPluginsboolean true是否把cracoConfig.babel.plugins应用到变换器的 plugins 中。当需要追加 Babel 配置时CRACO 会把 Jest 的 transform 入口替换为自带的jest-babel-transform并在jestConfig.globals._cracoConfig中注入整个 CRACO 配置merge-jest-config.ts使变换器在运行时能读到你的 Babel 设置。如果找不到^.\\.(js|jsx|mjs|cjs|ts|tsx)$这个标准 transform 入口会抛出明确错误。Babel 变换器的具体装配逻辑在 packages/craco/src/lib/features/jest/create-jest-babel-transform.ts它基于babel-preset-react-app构建变换器支持 JSX runtime 自动/经典两种模式可通过DISABLE_NEW_JSX_TRANSFORMtrue关闭新 JSX 变换再按addPresets/addPlugins追加你的 presets 与 plugins最后通过babelJest.createTransformer生成变换器实例。注意如果你没有在craco.config.js中配置babel字段jest.babel的这两个开关不会产生任何效果这是源码中if (cracoConfig.babel)分支所决定的。与 craco test 脚本模式的关系CRACO 还提供 CLI 模式craco test会把react-scripts的 Jest 配置提供者替换为经过 CRACO 合并的版本。其入口在 packages/craco/src/scripts/test.tsloadCracoConfigAsync(context).then((cracoConfig: CracoConfig) { validateCraVersion(cracoConfig); context.paths getCraPaths(cracoConfig); context.paths overridePaths(cracoConfig, context); overrideJest(cracoConfig, context); test(cracoConfig); });overrideJestpackages/craco/src/lib/features/jest/override.ts通过overrideJestConfigProvider把合并逻辑注入到react-scripts/utils/createJestConfig.js的模块缓存中packages/craco/src/lib/cra.ts随后才启动 CRA 的 test 脚本。注意 CLI 模式还会额外执行overridePaths即paths配置也会生效。两种模式的选择建议需要编辑器 Jest 集成、或想直接运行jestCLI使用本文的jest.config.jscreateJestConfig方案需要craco test的 watch/CI 集成、并希望paths等运行时覆盖一并生效使用 CLI 模式两者也可以共存CLI 模式负责运行时动态合并jest.config.js供工具链读取。实战注意事项与验证包版本一致性createJestConfig依赖react-scripts的utils/createJestConfig.js请确保项目中已安装对应版本的react-scripts若使用自定义 fork通过reactScriptsVersion指定即可。NODE_ENVcreateJestConfig在未设置NODE_ENV时默认置为development见 api.ts。在 npm script 中建议显式声明test: jest并自行管理环境变量或直接使用craco test。配置校验cracoConfig必须是对象不能是函数jest.configure若为函数则必须返回配置对象否则抛出错误。验证方式仓库的单元测试 test/unit/merging-tests/custom-jest-config/jest.test.js 与 jest.config.mock.js 展示了合并前后配置的断言方式可作为你本地验证createJestConfig输出结构的参考。最后若需要更完整的jest配置项说明configure支持任何 Jest 配置选项、jest.babel各开关的默认值等可进一步阅读 website/docs/configuration/jest.md关于对象字面量/函数两种写法的通用约定可参考 website/docs/configuration/getting-started.md。赞分享开发工具前端构建【免费下载链接】cracoCreate React App Configuration Override, an easy and comprehensible configuration layer for Create React App.项目地址https://gitcode.com/gh_mirrors/cr/craco点击查看免费下载相关推荐在 Create React App 项目中使用 craco-antdless 加载与 Ant Design 主题定制实战指南在 Create React App 项目中使用 craco antdless 加载与 Ant Design 主题定制实战指南 本文聚焦 CRACOCrea开发工具前端构建在Create React App中使用Material Tailwind的完整指南在Create React App中使用Material Tailwind的完整指南 前言 Material Tailwind是一个结合了Material DeUI库/组件前端在 Web 项目中使用 React Native Elementsreact-native-web 与 create-react-app 完整接入指南在 Web 项目中使用 React Native Elementsreact native web 与 create react app 完整接入指南 本指南UI组件移动开发前端上一篇如何使用react-jsonschema-form与Redux动作创建器设计模式构建高效表单应用下一篇Hermes Agent容器化部署终极指南从零构建可扩展的AI代理平台创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表