
开发工具前端构建【免费下载链接】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的babel配置项接入 MobX 状态管理库。文章以 use-mobx.md 为骨架结合 CRACO 的 Babel 覆盖实现源码与单元测试完整讲解装饰器语法启用、Babel 插件合并机制、配置文件放置与脚本启动方式以及 MobX 在现代非装饰器写法下的替代方案。读完本文你将掌握用craco.config.js一行配置让 CRA 项目跑通 MobX并理解 CRACO 在底层是如何安全地把自定义 Babel 插件注入 CRA 默认配置的。概述为什么在 CRA 中使用 MobX 需要 CRACOCreate React App 刻意隐藏了 webpack 与 Babel 配置目的是保证开箱即用的稳定性代价是开发者无法直接修改 Babel 插件列表。MobX 的经典写法observable、computed、action等类装饰器依赖 Babel 插件babel/plugin-proposal-decorators而 CRA 默认并不启用该插件。CRACO 的作用正是为 CRA 提供一层可配置覆盖层在不 eject 的前提下通过项目根目录的craco.config.js修改 Babel、webpack、Jest、DevServer 等配置然后用craco命令替代react-scripts启动项目。MobX 的官方使用场景与 CRACO 的 Babel 覆盖能力天然匹配你只需要在 CRACO 配置中追加一个 Babel 插件MobX 的装饰器语法即可在 CRA 项目中原样运行。这也正是 Use MobX 配方给出的最小化解决方案——全部配置只有一条 Babel 插件。最小配置在 craco.config.js 中启用 MobX 装饰器配置文件本身在项目根目录创建craco.config.js内容即官方配方给出的完整配置module.exports { babel: { plugins: [[babel/plugin-proposal-decorators, { legacy: true }]], }, };这段配置完成两件事告诉 Babel 使用babel/plugin-proposal-decorators插件以{ legacy: true }启用legacy传统装饰器语法这是 TypeScript 与 MobX 装饰器早期版本所采用的老式语义。若不设置legacy: trueBabel 会按 2018 年之后的新提案语义decorators提案的 stage 3 版本解析装饰器与 MobX 基于experimentalDecorators的用法不兼容。前置依赖安装要让上述配置生效需要先安装两个包npm install mobx mobx-react-lite npm install --save-dev babel/plugin-proposal-decorators其中mobx提供核心响应式状态能力observable、computed、action等mobx-react-lite是面向函数组件的 React 绑定库提供observer、useLocalObservable等 APIbabel/plugin-proposal-decorators作为 Babel 插件必须安装到项目本地Babel 才能找到它CRACO 不会替你安装 Babel 插件只负责把插件注入 CRA 的 loader 配置。修改 package.json 的启动脚本CRACO 通过自己的 CLI 包装 CRA 的react-scripts脚本因此需要把package.json中的脚本改为{ scripts: { start: craco start, build: craco build, test: craco test } }完成以上三步后在组件中使用 MobX 装饰器例如observable、computed、action即可被 Babel 正确解析。配置文件的查找与加载craco.config.js 从何而来craco.config.js之所以能被自动识别源于 CRACO 使用cosmiconfig按固定优先级搜索配置文件。在 config.ts 的源码中可以看到完整的候选文件名列表按优先级从高到低package.json中的cracoConfig字段显式指定文件路径优先级最高craco.config.tscraco.config.jscraco.config.cjs.cracorc.ts.cracorc.js.cracorcconst explorer cosmiconfigSync(moduleName, { searchPlaces: [ package.json, ${moduleName}.config.ts, ${moduleName}.config.js, ${moduleName}.config.cjs, .${moduleName}rc.ts, .${moduleName}rc.js, .${moduleName}rc, ], loaders: { .ts: tsLoader(), }, });loadCracoConfig会读取配置文件并执行processCracoConfig先用deepMergeWithArray把默认配置与用户配置合并见 utils.ts 中基于 lodashmergeWith的实现再应用plugins字段声明的 CRACO 插件最终得到生效配置。如果希望把 MobX 相关配置放到非默认位置可以在package.json中声明{ cracoConfig: config/craco.config.js }或通过 CLI 参数指定{ scripts: { start: craco start --config config/craco.config.js } }注意--configCLI 方式不支持 Babel 与 Jest 配合使用官方文档 getting-started.md 中已有明确 caution 提示。底层原理CRACO 如何把 Babel 插件注入 CRA定位 babel-loaderCRACO 对 Babel 的覆盖实现在 packages/craco/src/lib/features/webpack/babel.ts。入口函数overrideBabel的逻辑是先从 webpack 配置中按名字查找babel-loader通过getLoadersloaderByName(babel-loader)再对每一个匹配的 loader 调用overrideLoader注入用户配置。如果 CRA 的 webpack 配置中找不到任何babel-loader则会调用logError(Cannot find any Babel loaders.)并直接返回原配置。插件追加而非替换overrideLoader从cracoConfig.babel中取出presets、plugins、assumptions与loaderOptions四类配置。其中addPlugins的实现体现了 CRACO 最重要的设计原则——追加而不是替换function addPlugins(loader: RuleSetRule, babelPlugins: any[]) { if (isArray(babelPlugins)) { if (loader.options !isString(loader.options)) { if (loader.options.plugins) { loader.options.plugins loader.options.plugins.concat(babelPlugins); } else { loader.options.plugins babelPlugins; } } else { loader.options { plugins: babelPlugins, }; } } log(Added Babel plugins.); }也就是说你在craco.config.js里写的plugins数组会被concat到 CRA 原有的 Babel 插件列表末尾CRA 默认的babel/preset-react、babel/preset-env等既有配置完全不受影响。这正是 MobX 配方能只加一行插件就工作的原因CRACO 保留了 CRA 的默认 Babel 环境只是额外追加了装饰器支持。loaderOptions 的两种形态babel.loaderOptions既可以是一个对象字面量与 CRA 原 loader options 深度合并也可以是一个函数。函数签名如下loaderOptions: (babelLoaderOptions, { env, paths }) { // 修改或返回新的 loader options return babelLoaderOptions; };在applyLoaderOptions中可以看到函数形态会收到 CRA 原始的 loader options 与上下文env、paths返回值将直接替换 loader options对象形态则通过deepMergeWithArray与原配置合并。对于 MobX 场景我们通常只需要plugins字段无需触及loaderOptions若需要同时调整cacheDirectory、presets等 babel-loader 选项可以使用loaderOptions。单元测试的印证仓库中 test/unit/merging-tests/custom-babel-config/babel.test.js 直接验证了追加而非替换的合并语义it(correctly applies custom Babel presets, () { const babelConfig cracoConfig.babel.loaderOptions; expect(babelConfig.presets).toContain(babel/preset-env); expect(babelConfig.presets).toContain(babel/preset-react); expect(babelConfig.presets).toContain(babel/preset-typescript); }); it(does not remove existing Babel presets, () { const babelConfig cracoConfig.babel.loaderOptions; expect(babelConfig.presets.length).toBeGreaterThanOrEqual( babelConfigMock.presets.length ); });测试断言自定义 preset 被加入的同时CRA 原有的babel/preset-env、babel/preset-react依然存在、数量不减。这套语义同样适用于pluginsMobX 装饰器插件被追加进 CRA 的 Babel 插件链原有编译行为保持不变。完整实战示例一个带装饰器的 MobX store将配置与代码组合起来一个完整的 MobX 集成示例class 组件 装饰器写法如下import { makeObservable, observable, computed, action } from mobx; class CounterStore { count 0; constructor() { makeObservable(this, { count: observable, doubled: computed, increment: action, }); } get doubled() { return this.count * 2; } increment() { this.count 1; } } export default new CounterStore();import React from react; import { observer } from mobx-react-lite; import store from ./store; const App observer(() ( div pCount: {store.count}/p pDoubled: {store.doubled}/p button onClick{() store.increment()}1/button /div )); export default App;此例使用了 MobX 6 推荐的makeObservable显式标注因此不依赖装饰器若你的代码风格是传统装饰器observable count 0只需保留文章开头craco.config.js中的babel/plugin-proposal-decorators配置即可两种写法可以共存于同一 Babel 环境。运行npm start即craco start后CRACO 会加载 webpack 开发配置并调用 cra.ts 中的loadWebpackDevConfig、start等封装最终把 Babel 插件注入后启动 CRA 的react-scripts脚本craco build走同样的注入流程构建生产包。进阶MobX 装饰器配置的更多组合babel.plugins字段接受任意 Babel 插件条目格式与 Babel 官方一致——string或[string, options]元组。除了装饰器插件常见的 MobX 配套配置还可以这样组合module.exports { babel: { plugins: [ [babel/plugin-proposal-decorators, { legacy: true }], [babel/plugin-proposal-class-properties, { loose: true }], ], }, };如果你同时使用 MobX 的computed自动追踪与类属性初始化可能需要babel/plugin-proposal-class-properties具体依赖项以你的 Babel 与 MobX 版本实际要求为准。注意这些插件会被追加到 CRA 默认插件之后且不会移除任何 CRA 原有配置——这正是 babel.ts 中addPlugins用concat实现追加的根本原因。按环境条件启用配置若只想在开发环境启用某项 Babel 插件可利用 CRACO 提供的whenDev辅助函数来自 plugin-utils.ts完整用法见 getting-started.mdconst { whenDev } require(craco/craco); module.exports { babel: { plugins: [ [babel/plugin-proposal-decorators, { legacy: true }], ...whenDev(() [babel-plugin-macros], []), ], }, };whenDev(fn, unmetValue)等价于when(process.env.NODE_ENV development, fn, unmetValue)条件成立时调用fn并把返回值展开进数组否则展开unmetValue。使用函数形态动态计算 loaderOptions当 Babel 配置需要依赖当前环境时loaderOptions的函数形态更为灵活module.exports { babel: { loaderOptions: (babelLoaderOptions, { env, paths }) { if (env development) { babelLoaderOptions.cacheDirectory true; } return babelLoaderOptions; }, }, };总结与验证清单在 CRA 项目中使用 CRACO 接入 MobX核心步骤只有三步安装mobx、mobx-react-lite与babel/plugin-proposal-decorators在craco.config.js的babel.plugins中追加[babel/plugin-proposal-decorators, { legacy: true }]将package.json的脚本从react-scripts切换为cracocraco start/craco build/craco test。验证配置是否生效的快速方法是在组件中写一个observable装饰器字段运行npm start若浏览器无编译报错、状态可正常响应说明装饰器已成功启用。若编译报错提示无法解析装饰器请检查babel/plugin-proposal-decorators是否已安装到项目本地、legacy: true是否已设置以及脚本是否确实经由craco而非react-scripts启动。底层机制上CRACO 通过 babel.ts 中的getLoadersloaderByName(babel-loader)定位 CRA 的 Babel loader再用concat把自定义插件追加到原有插件列表之后全程不破坏 CRA 的默认编译配置这一行为有仓库内 babel.test.js 单元测试背书可放心使用。配置文件的自动发现与加载流程见 config.ts完整 Babel 配置项说明见 babel.md。备注本文涉及的命令与配置以当前仓库CRACO 7.x、react-scripts5.x为准不同 CRA 版本的 Babel 插件默认集可能不同若升级 CRA 大版本建议以craco build实际编译结果为准进行验证。赞分享开发工具前端构建【免费下载链接】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 配置增强工具——CRACOCreate React App 配置增强工具——CRACO CRACOCreate React App Configuration Override是一个开发工具前端构建使用 PurgeCSS 优化 ReactCreate React App项目craco、CLI 与 Webpack 插件三种方案详解使用 PurgeCSS 优化 ReactCreate React App项目craco、CLI 与 Webpack 插件三种方案详解 React 是用于构前端构建工具如何使用CRACO (Create React App Configuration Override)如何使用CRACO Create React App Configuration Override 本教程将指导你如何安装和使用CRACO一个用于配置Crea开发工具前端构建上一篇Telekasten.nvim一个强大的Neovim知识管理插件下一篇如何快速掌握Kubeflow Pipelines可视化与监控全面了解ML工作流运行状态创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考