
开发工具前端构建【免费下载链接】cracoCreate React App Configuration Override, an easy and comprehensible configuration layer for Create React App.项目地址https://gitcode.com/gh_mirrors/cr/craco点击查看免费下载CRACOCreate React App Configuration Override为 Create React App 提供了一层统一、易理解的配置覆盖能力。本篇指南聚焦于其中用于定制 Jest 测试环境的jest配置段完整讲解jest.babel与jest.configure两大配置项的用法、函数形式的 context 对象能力并结合仓库源码如 merge-jest-config.ts、create-jest-babel-transform.ts与单元测试深入剖析其底层合并原理与调用链。读完本文你将能够熟练地在craco.config.js中定制 Jest 的 Babel 转换行为、任意覆盖 Jest 配置项并理解对象字面量与函数两种配置模式的取舍。一、配置总览在craco.config.js中Jest 相关的配置全部收拢在jest键下结构如下module.exports { // ... jest: { babel: { addPresets: true /* (default value) */, addPlugins: true /* (default value) */, }, configure: { /* ... */ }, configure: (jestConfig, { env, paths, resolve, rootDir }) { /* ... */ return jestConfig; }, }, };:::tip上面大纲中重复出现的属性例如configure既可以赋值为对象字面量也可以赋值为函数。两者合并语义不同详见 配置技巧对象字面量与函数。:::从配置结构可以清晰看到两个核心维度jest.babel控制 CRACO 是否把你在babel配置段中声明的 presets / plugins 注入到 Jest 的 Babel 转换器里jest.configure允许你以对象合并或函数接管两种方式修改 Jest 最终配置。CRACO 对jest段的所有处理都发生在 merge-jest-config.ts 的mergeJestConfig中其处理顺序为先加载 CRA 提供的原始 Jest 配置 → 处理jest.babel的 Babel 转换器覆盖 → 应用jest.configure对象合并或函数接管→ 最后执行通过craco:jest插件注册的配置钩子。二、jest.babel控制 Babel 预设与插件的注入jest.babel只包含两个布尔选项用于决定 CRACO 是否把babel配置段中定义的 Babel presets 和 plugins 补充到 Jest 的转换流程中。其官方文档指向了 jestjs.io 的 Code Transformation 说明核心概念即babel-jest转换器。2.1 jest.babel.addPresets类型boolean默认值true是否将babel.presets注入到 Jest 使用的 Babel 配置中。置为false时CRACO 将只保留 CRA 默认的 Babel 预设即babel-preset-react-app忽略你在babel段额外声明的 presets。2.2 jest.babel.addPlugins类型boolean默认值true是否将babel.plugins注入到 Jest 使用的 Babel 配置中。置为false时额外声明的 Babel plugins 不会参与测试环境的编译。2.3 底层实现Babel 转换器是如何被覆盖的这两个选项在 merge-jest-config.ts 的configureBabel函数中被消费。源码逻辑如下const BABEL_TRANSFORM_ENTRY_KEY ^.\\.(js|jsx|mjs|cjs|ts|tsx)$; function configureBabel(jestConfig, cracoConfig) { const { addPresets, addPlugins } cracoConfig.jest?.babel ?? {}; if (addPresets || addPlugins) { if (cracoConfig.babel) { const { presets, plugins } cracoConfig.babel; if (isArray(presets) || isArray(plugins)) { if (!jestConfig.transform) { jestConfig.transform {}; } if (jestConfig.transform[BABEL_TRANSFORM_ENTRY_KEY]) { overrideBabelTransform(jestConfig, cracoConfig, BABEL_TRANSFORM_ENTRY_KEY); } else { throw new Error( craco: Cannot find Jest transform entry for Babel ${BABEL_TRANSFORM_ENTRY_KEY}. ); } } } } }几个值得注意的实现细节触发条件只有当addPresets或addPlugins为真且cracoConfig.babel中确实存在 presets 或 plugins 数组时才会去覆盖 Jest 的 transform 配置否则完全不干预。依赖默认 transform 键CRACO 会查找^.\\.(js|jsx|mjs|cjs|ts|tsx)$这个 CRA 默认的 Jest transform 条目。如果找不到例如你的 Jest 配置把该键删掉了会直接抛出craco: Cannot find Jest transform entry for Babel ...错误。通过 globals 传递配置overrideBabelTransform会把整个cracoConfig挂到jestConfig.globals._cracoConfig上实现思路参考了 facebook/jest 的 issue #1468随后将 transform 指向 CRACO 自带的./jest-babel-transform从而保证 Jest 工作线程能拿到 craco 配置jestConfig.globals jestConfig.globals || {}; jestConfig.globals._cracoConfig cracoConfig; jestConfig.transform[transformKey] require.resolve(./jest-babel-transform);2.4 真正的转换器create-jest-babel-transform被替换后的转换器由 create-jest-babel-transform.ts 生成。它基于babel-jest的createTransformer构建默认配置为const craBabelTransformer { presets: [ [ babel-preset-react-app, { runtime: hasJsxRuntime ? automatic : classic, }, ], ], babelrc: false, configFile: false, };默认保留babel-preset-react-app且会根据react/jsx-runtime是否可解析自动选择 JSXautomatic或classic运行时设置环境变量DISABLE_NEW_JSX_TRANSFORMtrue会强制回退到classic。babelrc: false与configFile: false表明该转换器不读取项目的.babelrc/babel.config.js一切以 CRACO 组合出的配置为准。当addPresets为真时会把babel.presets追加到上述 presets 之后当addPlugins为真时会把babel.plugins设为转换器的 plugins。而 jest-babel-transform.ts 则是运行时的入口第一次处理文件时通过loadCracoConfigAsync异步加载 craco 配置并构建真正的babel-jest转换器之后所有文件都用这份缓存的转换器处理既解决了转换器需要在运行前拿到配置的矛盾又避免了重复构建的开销。三、jest.configure覆盖任意 Jest 配置jest.configure是定制 Jest 行为的主入口支持两种赋值方式对应两种截然不同的合并策略。类型JestConfig或(config: JestConfig, { env, paths, resolve, rootDir }) JestConfig可选值范围任意 Jest 配置项如moduleNameMapper、transform、setupFiles、collectCoverageFrom、testPathIgnorePatterns等。3.1 对象字面量模式深合并当configure被赋值为普通对象时CRACO 使用deepMergeWithArray将你的配置与 CRA 原始 Jest 配置进行深合并jestConfig deepMergeWithArray({}, jestConfig, configureJest);深合并意味着嵌套对象如transform、moduleNameMapper不会整块覆盖而是逐键合并数组采用合并策略不会直接替换原有数组你只声明需要改动的键即可CRA 的其余 Jest 配置原样保留。单元测试 jest.test.js 中专门验证了这一点does not remove existing Jest configurations——合并后的配置键数量大于等于 CRA 原始配置。下面是一个典型的对象字面量示例它保留 CRA 的 Babel 转换、同时追加一个路径别名映射module.exports { jest: { configure: { transform: { ^.\\.[t|j]sx?$: babel-jest, }, moduleNameMapper: { ^components/(.*)$: rootDir/src/components/$1, }, }, }, };3.2 函数模式完全接管当configure被赋值为函数时CRACO 不再做深合并而是把 CRA 的原始 Jest 配置作为第一个参数交给你的函数由你全权决定返回什么jestConfig configureJest(jestConfig, context); if (!jestConfig) { throw new Error(craco: jest.configure function didnt returned a Jest config object.); }函数必须返回一个 Jest 配置对象否则 CRACO 会抛出错误这是总控制权模式源码中该函数恰如其名地叫作giveTotalControl你可以自由改写、删除、替换任何配置项而不受深合并策略约束该函数签名同样可以在 getting-started.md 的配置技巧 中找到通用约定。module.exports { jest: { configure: (jestConfig, { env, paths, resolve, rootDir }) { // 基于当前环境做差异化处理 jestConfig.setupFiles jestConfig.setupFiles || []; if (env test) { jestConfig.setupFiles.push(rootDir/src/setup-tests.js); } return jestConfig; }, }, };3.3 configure 的 context 对象env、paths、resolve、rootDir函数版本的configure会收到第二个参数——context 对象。除了与其他配置段共享的通用属性外Jest 段还额外提供两个由 CRA 提供的属性属性来源说明envCRACO当前NODE_ENVdevelopment、production、test等pathsCRACO一个包含 CRA 全部路径的对象appSrc、appPublic、appBuild、appHtml、appIndexJs、testsSetup等完整字段可参考 context.ts 中的CraPathsresolveCRA由 CRACO 包装的require.resolve用于在react-scripts或reactScriptsVersion指定的包内解析模块路径rootDirCRA项目根目录在 merge-jest-config.ts 中resolve与rootDir是这样构建的const customResolve (relativePath: string) require.resolve( path.join(cracoConfig.reactScriptsVersion ?? react-scripts, relativePath), { paths: [projectRoot] } ); const jestContext { ...context, resolve: customResolve, rootDir: projectRoot, };resolve让你可以按相对路径解析 CRA 内部模块例如resolve(config/jest/cssTransform.js)这在引用 CRA 自带的 Jest 工具模块时非常有用rootDir固定为项目根目录可用它拼出指向项目内文件的绝对路径reactScriptsVersion未配置时默认解析react-scripts包若你使用了 CRA 的 fork 包可以在配置中通过reactScriptsVersion指定参见 getting-started.md。对应的类型定义见 context.tsexport interface JestContext extends BaseContext { resolve?: (id: string) string; rootDir?: string; }3.4 一条链路贯穿到底craco test 是如何工作的jest配置段不仅在 Jest 配置生成时生效CRACO 的craco test命令也走同一套覆盖逻辑。scripts/test.ts 的启动流程为设置NODE_ENV为test若未设置加载 craco 配置校验 CRA 版本获取并覆盖 CRA paths调用overrideJest(cracoConfig, context)把 Jest 配置提供者替换为 CRACO 合并后的结果见 override.ts其内部同样调用mergeJestConfig最后执行 CRA 的test脚本。另外如果你需要以编程方式生成 Jest 配置例如在自定义 CI 脚本中可以使用 api.ts 导出的createJestConfig(cracoConfig, callerContext, options)。它会完成NODE_ENV兜底、craco 配置处理、路径获取并最终调用mergeJestConfig返回一份完整的 JestInitialOptions。四、实践建议与常见问题4.1 推荐用法只需增补配置项别名、setup 文件、覆盖率配置优先使用对象字面量形式的configure借助深合并天然继承 CRA 默认值且与单元测试中不删除已有配置的行为保持一致需要条件化改写、删除配置或依赖 context使用函数形式配合env、resolve、rootDir做差异化处理想让 craco 的 Babel presets/plugins 同时作用于测试环境保持jest.babel.addPresets/addPlugins为默认的true若测试环境需要纯净的babel-preset-react-app则显式置为false。4.2 常见报错与排查craco: Cannot find Jest transform entry for Babel ^.\.(js|jsx|mjs|cjs|ts|tsx)$说明你的jest.configure移除了 CRA 默认的 transform 键。若同时启用了jest.babelCRACO 将无法挂载自定义 Babel 转换器。此时应保留该 transform 键或改用函数形式自行接管 transform。craco: jest.configure function didnt returned a Jest config object.函数形式的configure忘记返回jestConfig。CRACO 对未返回配置的情况做了显式校验见giveTotalControl。craco: cracoConfig is required./cracoConfig should be an object.调用createJestConfig时未传配置或传入了函数均会被 api.ts 拒绝。4.3 验证路径单元测试jest.test.js 验证了对象字面量合并行为与不删除既有配置的语义配套配置示例craco.config.js核心实现merge-jest-config.ts、create-jest-babel-transform.ts、jest-babel-transform.ts类型定义context.ts。五、小结CRACO 的jest配置段虽然只有两个键却覆盖了测试环境定制的完整闭环jest.babel控制 Babel 预设/插件是否注入默认均开启jest.configure则以深合并对象或函数总接管两种模式让你触碰任意 Jest 配置项并通过resolve、rootDir等扩展 context 属性获得与 CRA 内部模块协作的能力。理解 merge-jest-config.ts 中先 Babel、再 configure、最后插件钩子的处理顺序将帮助你在排查问题时快速定位行为来源。赞分享开发工具前端构建【免费下载链接】cracoCreate React App Configuration Override, an easy and comprehensible configuration layer for Create React App.项目地址https://gitcode.com/gh_mirrors/cr/craco点击查看免费下载相关推荐在 CRACO 中为 Jest 配置 Webpack 别名moduleNameMapper 实战指南在 CRACO 中为 Jest 配置 Webpack 别名moduleNameMapper 实战指南 本篇技术指南面向使用 Create React App开发工具前端构建Laravel CORS深度解析从原理到实战的完整配置指南Laravel CORS深度解析从原理到实战的完整配置指南 跨域资源共享CORS是现代Web开发中不可或缺的安全机制而Laravel CORS扩展包则为后端在 webpack 项目中使用 Jest从 webpack 配置到 Jest 配置的完整迁移指南在 webpack 项目中使用 Jest从 webpack 配置到 Jest 配置的完整迁移指南 本指南聚焦于如何在基于 webpack 构建的前端项目尤其测试质量保障代码覆盖率开发工具上一篇QMUI_Android中的矢量图标使用减小APK体积的有效方法下一篇最完整的Flet入门指南从安装到部署30分钟打造你的第一个跨平台应用创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考