Carbon carbon/upgrade基于 jscodeshift 的 Carbon 版本升级与 v12 迁移 Codemod 实战指南【免费下载链接】carbonA design system built by IBM项目地址: https://gitcode.com/GitHub_Trending/carbo/carboncarbon/upgrade是 Carbon 设计系统IBM 的开源设计系统提供的命令行升级工具它将依赖包更新与源码自动改写codemod封装为两个命令upgrade与migrate。本文以仓库中 packages/upgrade/README.md 为骨架结合 CLI 入口源码、迁移命令实现、迁移注册表 与 jscodeshift 封装 展开讲解读完你可以独立完成 Carbon v11 的依赖升级并运行全部 v12 Feature Flag 相关的 codemod把应用平滑迁移到 Carbon v12。安装与调用方式将carbon/upgrade安装为项目依赖包清单 中当前版本为11.45.0核心运行依赖是jscodeshiftnpm install -S carbon/upgrade如果偏好 Yarnyarn add carbon/upgrade也可以不安装直接用npx在项目中临时运行npx carbon/upgradeCLI 命令与选项全览carbon/upgrade的完整帮助输出如下源自 READMEUsage: carbon/upgrade [options] Commands: carbon/upgrade upgrade upgrade your project [default] carbon/upgrade migrate migration run a Carbon migration on your [paths...] source files carbon/upgrade migrate list list all available migrations Options: --help Show help [boolean] --version Show version number [boolean] --force force execution if the cli encounters an error while doing safety checks [boolean] [default: false] -w, --write update the files with changes found by running the migration [boolean] [default: false] -v, --verbose optionally include additional logs, useful for debugging [boolean] [default: false] --decoratorsBeforeExport parse decorators before export declarations [boolean] [default: false]对照 cli.js 可以看到upgrade是默认命令$0选项通过 yargs 声明后透传给两条命令的实现。各选项的实际作用选项作用默认值-w, --write将迁移结果写回文件不加该参数时只做 dry-run 预览false--force跳过 git 工作区干净性安全检查并强制执行false-v, --verbose输出更详细的调试日志false--decoratorsBeforeExport解析“export 声明之前的装饰器”语法透传给 jscodeshift 的 babel 插件false在 cli.js 的run()包装函数中还有一个值得注意的安全机制命令执行前会调用is-git-clean检查当前 git 仓库是否有未提交的改动若工作区不干净且未传--forceCLI 会打印黄色警告并以退出码 1 终止提示你先stash或commit。这避免了 codemod 直接覆盖你尚未保存进版本库的代码。upgrade 命令依赖包更新upgrade命令默认命令负责更新package.json中的依赖并在必要时执行关联的源码迁移。其实现见 commands/upgrade.js工作区发现通过 workspace.js 在cwd下寻找可用工作区含package.json的目录。单工作区直接使用多工作区时通过inquirer交互式让你选择。升级方案匹配在 upgrades.js 中注册了三套升级方案CLI 用semver.intersects比对工作区现有依赖版本与方案要求的版本区间如carbon-components需处于10.xv11: full update——将carbon-components、carbon-components-react、carbon-icons、carbon/icons-react全部收敛到carbon/reactv11: default update——将carbon-components、carbon-components-react、carbon-icons替换为carbon/react并附带一组源码迁移import 改写、size prop 更新等v11: carbon-components——仅将carbon-components替换为carbon/styles。应用变更对每个方案按Change.install/Change.update/Change.uninstall三类变更改写package.json。加--write时写盘否则只打印 diff 预览见 upgrade.js 中的 packageJson 处理。执行关联迁移方案中migrations列表里的每个 codemod 会依次运行例如update-carbon-components-react-import-to-scoped把carbon-components-react的 import 改写为carbon/react、update-carbon-icons-react-import-to-carbon-react把carbon/icons-react改写为carbon/react/icons等。migrate 命令运行单个迁移migrate migration [paths...]允许你在自己的源文件上单独运行某一个迁移migrate list则列出所有可用迁移。commands/migrate.js 的逻辑是从升级注册表中收集所有migrations定义指定了options.migration时按名称精确查找找不到会报错并自动打印可用迁移清单迁移执行时若未提供paths会在工作区内按 glob 收集*.js / *.jsx / *.ts / *.tsx并统一忽略es/、lib/、umd/、node_modules/、storybook-static/、dist/、build/、*.d.ts、coverage/等产物目录见 upgrades.js 中各迁移的默认 glob 配置迁移完成后若该迁移声明了messageConfig且非 dry-run终端会额外打印迁移总结与后续步骤。这些迁移本质上是基于 jscodeshift 运行器的 codemod源码位于 transforms 目录。transforms/ARCHITECTURE.md 还说明了如何不经过 CLI、直接调用单个 transform# 对指定路径运行某个 transform yarn jscodeshift -t transforms/name.js path/to/file # 用 dry print 预览将要发生的改动 yarn jscodeshift -d -p -t transforms/name.js path/to/file底层运行细节所有迁移最终经由 src/jscodeshift.js 封装的Runner.run执行。从该文件可以看到几个关键事实默认 parser 为babylon部分迁移如enable-v12-release、slug-prop-to-decorator-prop显式传入parser: tsx以正确解析 TypeScript JSXparserConfig开启了jsx、typescript、decorators等 babel 插件--decoratorsBeforeExport选项即通过[decorators, { decoratorsBeforeExport }]生效全局ignorePattern会排除build/、dist/、es/、lib/、node_modules/、storybook-static/、umd/以及.md、.css、.scss、yarn.lock等文件确保 codemod 只触碰源码dry由 CLI 的--write决定dry: !options.write即默认只预览不落盘verbose为 true 时以verbose: 2传给 jscodeshift 输出更多日志。每个迁移都配有测试与 fixture__tests__目录中的测试驱动__testfixtures__中*.input.js或.tsx到*.output.js的断言保证变换结果可预测、输出一致约定见 transforms/ARCHITECTURE.md。输出格式化建议codemod 的输出格式可能与你代码库的格式化风格不一致README 明确建议将 codemod 结果统一过一次自动格式化工具如 Prettier再提交。Feature Flag Codemods面向 Carbon v12 的迁移以下 codemods 帮助你提前采纳 v12 中由 feature flag 引入的变更把代码改造成在特定 feature flag 开启状态下可运行的形态。enable-v12-release启用 v12 完整体验npx carbon/upgrade migrate enable-v12-release --write该 codemod 将 React 根节点渲染的应用包裹在FeatureFlags enableV12Release中并添加或更新所需的carbon/reactimport它同时支持现代createRoot/hydrateRoot入口以及旧版ReactDOM.render。示例// Before import { createRoot } from react-dom/client; import App from ./App; const root createRoot(document.getElementById(root)); root.render(App /); // After import { createRoot } from react-dom/client; import { FeatureFlags } from carbon/react; import App from ./App; const root createRoot(document.getElementById(root)); root.render( FeatureFlags enableV12Release App / /FeatureFlags );示例// Before import { Tile } from carbon/react; TileContent/Tile; // After import { Tile } from carbon/react; import { FeatureFlags } from carbon/feature-flags; FeatureFlags enableV12TileDefaultIcons TileContent/Tile /FeatureFlags;enable-v12-overflowmenuOverflowMenu 迁移到 Menu 架构npx carbon/upgrade migrate enable-v12-overflowmenu --write提供两种模式默认带 FeatureFlags 包裹仅 API 迁移适用于根节点已使用 FeatureFlags 的应用npx carbon/upgrade migrate enable-v12-overflowmenu --wrapWithFeatureFlagfalse --write该 codemod 会把OverflowMenuItem转换为MenuItem组件映射属性itemText→label、isDelete→kinddanger为带hasDivider的项添加MenuItemDivider按需包裹FeatureFlags enableV12Overflowmenu--wrapWithFeatureFlag在 cli.js 中默认为true。带包裹的示例// Before OverflowMenu OverflowMenuItem itemTextOption 1 / OverflowMenuItem itemTextDelete isDelete / /OverflowMenu // After FeatureFlags enableV12Overflowmenu OverflowMenu MenuItem labelOption 1 / MenuItem labelDelete kinddanger / /OverflowMenu /FeatureFlags不带包裹仅 API 变更的示例// Before OverflowMenu OverflowMenuItem itemTextOption 1 / OverflowMenuItem itemTextDelete isDelete / /OverflowMenu // After OverflowMenu MenuItem labelOption 1 / MenuItem labelDelete kinddanger / /OverflowMenuenable-v12-tile-radio-iconsRadioTile 默认图标npx carbon/upgrade migrate enable-v12-tile-radio-icons --write把RadioTile组件以及包含RadioTile的TileGroup包裹在FeatureFlags enableV12TileRadioIcons中。// Before RadioTile valueoption1Option 1/RadioTile // After FeatureFlags enableV12TileRadioIcons RadioTile valueoption1Option 1/RadioTile /FeatureFlagsenable-v12-structured-list-visible-iconsStructuredList 选择图标常显npx carbon/upgrade migrate enable-v12-structured-list-visible-icons --write该 codemod为StructuredListRow添加selection属性移除单元格中手写的CheckmarkFilled图标既支持直接的组件写法也支持由函数生成的 JSX。// Before StructuredListWrapper selection StructuredListRow StructuredListCellData/StructuredListCell StructuredListCell {isSelected CheckmarkFilled /} /StructuredListCell /StructuredListRow /StructuredListWrapper // After StructuredListWrapper selection StructuredListRow selection StructuredListCellData/StructuredListCell /StructuredListRow /StructuredListWrapper值得注意这个迁移在 upgrades.js 中额外声明了messageConfig运行结束后 CLI 会提醒你还需手动开启 Sass 侧的 feature flag$enable-v12-structured-list-visible-icons: true——这正是“codemod 只改 React 标记、不改 Sass 配置”这一已知限制的具体体现。已知限制README 明确列出了这组 codemods 的边界执行前务必了解tile default icons、tile radio icons、OverflowMenu 这几个 codemod 生成的FeatureFlagsimport 来自carbon/feature-flags而 JSX 组件实际由carbon/react导出使用前需要自行修正生成的 importtile default icons codemod 的目标是Tile而 v12 默认图标行为实际影响ClickableTile使用前请核对覆盖面OverflowMenu codemod 只更新子项组件与子项属性不更新父级属性如aria-label→label需对照 v12 API 逐个检查迁移后的OverflowMenustructured list codemod 只改 React 标记不会更新应用中的 Sass feature flag 配置。其他 v12 Codemodsrefactor-light-to-layerlight 属性重构为 Layer 包裹npx carbon/upgrade migrate refactor-light-to-layer --write找出所有带light属性的组件移除light属性用Layer包裹组件并补充必要的 import。// Before import { Button } from carbon/react; Button lightClick me/Button; // After import { Button, Layer } from carbon/react; Layer ButtonClick me/Button /Layer;slug-prop-to-decorator-propslug 属性改名npx carbon/upgrade migrate slug-prop-to-decorator-prop --write// Before Component slugmy-identifierContent/Component // After Component decoratormy-identifierContent/Componentunstable-pagination-to-pagination不稳定版分页组件转正npx carbon/upgrade migrate unstable-pagination-to-pagination --write将unstable_Pagination/preview_Pagination迁移到稳定版Pagination并删除PageSelector的 import 与 children render-prop稳定版组件默认渲染等价的页码选择控件// Before import { unstable_Pagination as Pagination, unstable_PageSelector as PageSelector, } from carbon/react; Pagination pageSizes{[10, 20, 30]} totalItems{100} {({ currentPage, onSetPage, totalPages }) ( PageSelector currentPage{currentPage} onChange{(event) onSetPage(event.target.value)} totalPages{totalPages} / )} /Pagination; // After import { Pagination } from carbon/react; Pagination pageSizes{[10, 20, 30]} totalItems{100} /;自定义的页码选择 children 会被移除并留下TODO注释提示你按需用renderPageSelect迁移省略pageSizes即可隐藏每页条数选择器。对应的测试 fixture 见testfixtures/unstable-pagination-to-pagination.input.tsx。featureflag-deprecate-flags-propflags 对象改为布尔属性npx carbon/upgrade migrate featureflag-deprecate-flags-prop --write// Before FeatureFlags flags{{ enable-v12-tile-default-icons: true }} App / /FeatureFlags // After FeatureFlags enableV12TileDefaultIcons App / /FeatureFlags从 upgrades.js 的注册描述看该迁移还会清理已不再需要的 flag如enable-v11-release。TypeScript 支持全部 codemod 同时支持 TypeScript 文件.ts/.tsx与 JavaScript 文件.js/.jsx。从源码结构看这依赖 jscodeshift.js 中开启的typescript解析插件以及各迁移按需传入的parser: tsx。迁移的测试保障每个 transform 都遵循统一的结构以sort-prop-types为例见 transforms/ARCHITECTURE.mdtransforms/ ├── __testfixtures__/ │ ├── sort-prop-types.input.js │ └── sort-prop-types.output.js ├── __tests__/ │ └── sort-prop-types-test.js └── sort-prop-types.js*.input.js交给 transform 处理测试断言结果与*.output.js一致。以 v12 系列为例仓库中提供了成对的 JS/TSX fixture如 enable-v12-release.input.tsx、enable-v12-overflowmenu-nowrap.output.tsx并在 transforms/tests中由*-test.js驱动。这保证了你在自己项目上运行时变换行为与仓库测试中的行为一致。参考文件packages/upgrade/README.md本文的原始文档packages/upgrade/src/cli.jsCLI 选项定义与 git 安全校验packages/upgrade/src/commands/migrate.jsmigrate 命令实现packages/upgrade/src/commands/upgrade.jsupgrade 命令实现packages/upgrade/src/upgrades.js升级方案与全部迁移的注册表packages/upgrade/src/jscodeshift.jsjscodeshift 运行封装parser 配置与忽略规则packages/upgrade/transforms/ARCHITECTURE.mdtransform 编写与 fixture 约定packages/upgrade/transforms/全部 codemod 源码与测试 fixtureLICENSEApache 2.0 许可【免费下载链接】carbonA design system built by IBM项目地址: https://gitcode.com/GitHub_Trending/carbo/carbon创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考