尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Nx 迁移清单 migrations.json 编写指南:从 generators 条目到 packageJsonUpdates 分组

Nx 迁移清单 migrations.json 编写指南:从 generators 条目到 packageJsonUpdates 分组 Nx 迁移清单 migrations.json 编写指南从 generators 条目到 packageJsonUpdates 分组【免费下载链接】nxThe Monorepo Platform that amplifies both developers and AI agents. Nx optimizes your builds, scales your CI, and fixes failed PRs automatically. Ship in half the time.项目地址: https://gitcode.com/GitHub_Trending/nx/nx导读本文以 Nx monorepo 仓库内的迁移清单模板文档为主体系统讲解migrations.json的完整编写规范从generators段落的 generator-only、prompt-only、hybrid 三类迁移条目到packageJsonUpdates分组的版本门控与依赖升级策略再到插件首个迁移所需的package.json、assets.json等配套接线。读完你将掌握为 Nx 插件编写可被nx migrate正确收集、门控与执行的迁移清单的技能并理解版本字段、requires门控与 dist 路径形状背后的运行时契约。migrations.json是 Nx 迁移体系的注册中心每个 Nx 插件通过它宣告当工作区升级到某个版本时需要运行哪些迁移、升级哪些依赖。本文模板文档位于 .claude/skills/author-migration/templates/migrations-json.md配套的完整编写守则见 .claude/skills/author-migration/SKILL.md运行时契约见 .claude/skills/author-migration/runtime-contract.md。仓库中真实迁移清单可参考 packages/eslint/migrations.json、packages/storybook/migrations.json 等 30 余个插件的同名文件。migrations.json 的整体结构所有迁移条目挂在该文件顶层的generators段落schematics是 Angular Devkit 适配器的遗留段新条目一律写入generatorspackageJsonUpdates分组则挂在同级的packageJsonUpdates段落。文件底部给出了完整的骨架形状{ $schema: ../../node_modules/nx/schemas/migrations-schema.json, generators: {}, packageJsonUpdates: {} }$schema指向仓库 packages/nx/schemas/migrations-schema.json其中定义了generators、schematics、packageJsonUpdates三个顶层键及每个条目的合法字段。类型层面MigrationsJsonEntry与PackageJsonUpdates定义在 packages/nx/src/config/misc-interfaces.ts 中其中MigrationsJsonEntry包含version、description、implementation/factory、prompt、requires、documentation等可选字段并明确documentation是补充性的参考文档绝不代替implementation/prompt本身。版本字段与门控version 是闸门而非标签模板文档开篇即强调JSON 块中的条目键、版本值与包名都是示意性的真正构成契约的是键集合与路径形状。版本值遵循 SKILL.md 第 2 节的 target-train目标发布线规则。在 runtime-contract.md 中这一规则被进一步精确化条目在gt(version, installed) lte(version, target)时被收集采用 semver 预发布排序beta.N rc.N stable已安装一侧是严格大于gt用户恰好处于该预发布版本时永远不会再运行它因此绝不能写裸的正式版本号预发布用户会跳过它也绝不能回填旧预发布版本已越过该预发布的用户会被静默跳过同一次变更中的所有条目统一使用所选发布线确切的下一个预发布版本即使是在批量关联迁移时也是如此。实际运行逻辑可以在 packages/nx/src/command-line/migrate/migrate.ts 中看到requires求值统一使用includePrerelease: true。版本字段只决定何时触发迁移不决定哪个发布线承载这段代码——后者由分支决定破坏性迁移必须等待发布线切换后再合并。路径形状dist 前缀与 rootDir 映射模板文档明确指出implementation、prompt、documentation的路径带dist前缀因为它们要在已安装的包内部解析。运行时通过require.resolve以已安装包的migrations.json所在目录为基准解析这些路径所以路径必须匹配发布后的布局。rootDir: .主导形状发布路径为./dist/src/migrations/...模板中的示例正是这种形状rootDir: src发布时不含src段路径为./dist/migrations/...例如 packages/dotnet/migrations.json 中的implementation: ./dist/migrations/update-23-0-0/update-plugin-path。编写建议从同插件的兄弟条目复制形状若是插件首个条目则从该包的tsconfig.lib.json的rootDir推导。migration-markdown-assets一致性规则会把每个已发布的.md路径通过构建时的rootDir/outDir反映射回源码路径形状错误在rootDir: src的包中写./dist/src/...会直接失败而对未声明rootDir/outDir组合的包该规则不检查需要手工对照构建出的dist/确认路径。另外模板文档提醒prompt文件AI 提示词 runbook的文件名必须与 implementation 的 basename 不同——documentation的.md拥有该名称SKILL.md 第 4 节。这是为了避免 prompt 文档与实现文档同名而互相覆盖语义。Generator-only 条目确定性源码变换最基础的条目类型适用于删除选项、键重命名、默认值翻转等可静态检测、可确定性变换的变更update-23-2-0-remove-foo-option: { version: 23.2.0-beta.3, description: Removes the deprecated foo option from the nx/bar:build executor options, implementation: ./dist/src/migrations/update-23-2-0/remove-foo-option, documentation: ./dist/src/migrations/update-23-2-0/remove-foo-option.md }要点implementation指向编译后的默认导出迁移函数运行时以await fn(tree, {})调用#symbol语法可选中命名导出每条 generator 条目都必须配套同名的documentation.mdSKILL.md 第 6 节渲染在插件迁移文档页并作为 agentic 流程中 agent 的参考材料description同时喂给 agentic prompt 与公开文档页应描述具体动作例如从 nx/bar:build executor options 中移除已废弃的foo选项。当迁移只在上游主版本升级之后才适用时追加requiresrequires: { bar: 4.0.0 }requires的语义值得特别注意详见 runtime-contract.md它针对本次运行中该包将要落地的版本求值先取待执行的 packageJsonUpdates回退到已安装版本包在两者中都不存在则门控失败只在收集阶段求值一次执行阶段绝不重查——所以用上界编码源窗口如9 10会在同一次运行把包升过上限时失败且迁移永不执行storybook 曾因该 bug 被修复为去掉上界只有迁移在等于或高于某版本时确实不适用上界才正确如 packages/next/migrations.json 中落地在 next 16 的工作区对 next 15 指引无用的next 15.0.0 16.0.0requires是跨包 AND 语义互斥条件需要拆成多个条目无法用requires表达的 OR 条件如 umbrella 与 scoped 两种依赖名要在迁移函数内部用getDeclaredPackageVersion semver 做代码级门控——eslint 的hasTypescriptEslintV8见 packages/eslint/src/migrations/update-23-1-0/remove-removed-typescript-eslint-extension-rules.ts正是由此而来曾因单名门控静默跳过了只声明另一名字的工作区。Prompt-only 条目由 AI 驱动的判断型迁移当变更需要 AST 变换无法做出的判断时使用 prompt-only 条目——只有prompt与documentation没有implementationupdate-23-2-0-migrate-bar-config-format: { version: 23.2.0-beta.3, requires: { bar: 4.0.0 }, description: AI-assisted migration: rewrites bar config files to the v4 format, whose options do not map 1:1, so it is driven by an AI prompt rather than a deterministic generator, prompt: ./dist/src/migrations/update-23-2-0/migrate-bar-config-format.md, documentation: ./dist/src/migrations/update-23-2-0/upgrade-to-bar-v4.md }仓库真实示例packages/eslint/migrations.json 中的update-23-1-0-migrate-ban-types-rule——typescript-eslint/ban-types规则迁移到 v8 后继规则时选项无法 1:1 映射因此由 AI prompt 驱动而非确定性 codemod。prompt运行时语义生成阶段内容被提取到tools/ai-migrations/package/targetVersion/basename.md且仅在 agentic 流程下执行在普通运行中它们只作为下一步建议呈现。因此必须发生的变更绝不能放进 prompt——prompt-only 是最后手段用于完全没有可安全自动化子集的变更只要存在机械性子集就应该写 hybrid。Hybrid 条目确定性预扫描加 AI 收尾一个条目同时携带implementation与prompt两个键update-23-2-0-convert-bar-config: { version: 23.2.0-beta.3, requires: { bar: 4.0.0 }, description: Converts bar configuration to the v4 format; mechanically safe conversions are applied by a generator and the remainder is completed by an AI prompt, implementation: ./dist/src/migrations/update-23-2-0/convert-bar-config, prompt: ./dist/src/migrations/update-23-2-0/finish-bar-config-conversion.md, documentation: ./dist/src/migrations/update-23-2-0/convert-bar-config.md }规则与语义prompt 文件名必须与 implementation basename 不同documentation的.md拥有该名称eslint 的convert-to-flat-config因共享 basename 早于该命名规则模板文档明确提示不要照抄这一点hybrid 的生成器半边始终运行当该半边返回skipAgentic: true时跳过 prompt 半边——这是告诉运行器确定性运行已覆盖一切不需要 AI 步骤的显式信号通常来自迁移自身的 no-op 守卫.ts只做机械安全编辑把每个无法处理的形状累积成人类可读描述通过返回{ nextSteps, agentContext }分发给不同消费者agentContext只喂给 agent并在外层 agent 驱动nx migrate时输出到 stdoutnextSteps展示给人类用户且绝不进入 agent prompt返回skipAgentic: true时绝不能同时返回agentContext该上下文正是要喂给被放弃的 AI 步骤的。packageJsonUpdates声明式依赖升级普通升级针对目标发布线的普通依赖升级不需要写任何.ts实现23.2.0: { version: 23.2.0-beta.3, packages: { bar: { version: ^4.1.0, alwaysAddToPackageJson: false } } }alwaysAddToPackageJson: false只在包已安装的位置升级它这是受管依赖的常态true或字符串dependencies/devDependencies在缺失时也会把它加入 package.json分组应用条件为installed group.version target含下界与迁移条目不同只有已在 dependencies/devDependencies 中的包会被触及除非设置了addToPackageJson/alwaysAddToPackageJson跨分组按包取最高版本写回时过滤降级。跨主版本升级源主版本窗口门控每个受支持的源主版本一个分组按最旧在前排序23.2.0-bar-v4: { version: 23.2.0-beta.3, requires: { bar: 3.0.0 4.0.0 }, packages: { bar: { version: ^4.1.0, alwaysAddToPackageJson: false } } }与迁移条目不同packageJsonUpdates分组按源主版本窗口门控N.0.0 N1.0.0且必须同时携带上下界——分组把源范围翻译为目标版本阶梯依赖每个窗口闭合。分组按键序求值每个被接受的分组写入后续门控检查可读取的待更新集合被门控卡住的分组不会丢弃首轮之后持续重估直到没有更多分组适用包括另一插件稍后才满足门控的分组每个分组至多应用一次。这正是多主版本链式升级得以串联的机制——SKILL.md 中以 packages/rspack/migrations.json 未门控的 http-proxy-middleware v2→v3 升级与 packages/react/migrations.json 中同一提交后来被门控的升级对比强调老主版本仍受支持时跨主版本升级必须门控源窗口。分组键是用户可见的交互式提示页脚的文档锚点X.Y.Z或X.Y.Z-topic单独门控的第三方升级。packages/eslint/migrations.json 中的成对分组21.2.0-typescript-eslint/21.2.0-typescript-eslint正是用每名字一个分组来表达 OR 条件umbrella 与 scoped 依赖名。注意version--PackageGroup键由运行时从插件packageGroup合成绝不手工编写。升级自带迁移的包而不触发它们packages: { some-cli: { version: ~5.0.0, alwaysAddToPackageJson: false, ignorePackageGroup: true, ignoreMigrations: true } }ignorePackageGroup: trueignoreMigrations: true使升级只改版本不把该包的整个 packageGroup 拉进来也不触发它自带的迁移angular/cli模式见 runtime-contract.md。此外不要使用x-prompt已废弃Nx v24 移除schema 中标注为 Surfaced vianx migrate --interactive... will be removed in Nx v24ifPackageInstalled是运行时门控没有任何一方插件使用它一律改用requires。插件首个迁移package.json 接线当插件首次引入迁移时除了migrations.json本身还需要在 packages/eslint/package.json 之类的插件package.json中声明nx-migrations: { migrations: ./migrations.json, supportsOptionalMigrations: true }同时确认以下配套项SKILL.md 第 3 节缺一不可migrations.json以$schema: ../../node_modules/nx/schemas/migrations-schema.json开头仅新文件不回填旧文件assets.json把src/migrations/**/*.md复制进 dist使每个.md落在构建出的实现旁边rootDir: src的包用{ glob: migrations/**/*.md, input: packages/plugin/src }见 packages/maven/assets.json——缺少该 glob 会把.md从发布包中剔除破坏prompt/documentation解析与文档站migration-markdown-assets一致性规则会对任何未被 assets 配置产出的.md引用报错存在根级migrations.spec.ts调用nx/devkit/internal-testing-utils的assertValidMigrationPaths解析每个条目的 implementation/prompt/documentation 路径并标记孤立文件插件 eslint 配置把nx/nx-plugin-checks应用到含./migrations.json的files数组校验清单形状与重复键全新nx/*插件必须加入 packages/nx/package.json 的nx-migrations.packageGroup否则nx migrate永远不会升级它由nx-package-group一致性规则强制。模板文档还提醒不要只依赖nx/plugin:migration生成器——它只搭出空壳、默认键名取裸文件名且从不写requires、.md文件、prompt 条目或按包的packageJsonUpdates细节。应从模板文档手工编写。避坑清单与验证结合 .claude/skills/author-migration/deprecated-patterns.md 与 SKILL.md 第 7 节常见的正确性陷阱包括路径对但文件错没有校验器能检查路径是否指向正确的那个迁移文件——一个存在但错误的 implementation 路径能通过全部校验并在运行时执行packages/nx曾真实出现过该 bug务必打开文件人工确认不要编写clischema 标注 No longer used与schemaschema 有记录但运行时从不读取不要为nx/core之外的迁移编写x-repair-skipnx repair会无条件重跑所有 nx-core 迁移因此 nx-core 迁移必须幂等迁移函数签名固定为export default async function update(tree: Tree)只返回void | string[] | { nextSteps, agentContext, skipAgentic }任何GeneratorCallback都会被静默丢弃修复已发布迁移时就地修改实现并把条目版本提升到当前下一个预发布使已运行过坏版本的工作区能够重跑packages/storybook/migrations.json 展示了从21.1.0到23.2.0-test-runner的完整分组演化。发布前验证npx nx run-many -t test,lint -p plugin跑根级migrations.spec.ts与 lintnpx nx build workspace-plugin pnpm nx-cloud conformance:check跑migration-markdown-assets、migration-groups同一分组内所有typescript-eslint/*必须一起升级与nx-package-group规则最后在真实仓库中通过本地 registrypnpm local-registrypnpm nx-release next-prerelease --local或离线 tarball 方式端到端验证一次npx nx migrate。【免费下载链接】nxThe Monorepo Platform that amplifies both developers and AI agents. Nx optimizes your builds, scales your CI, and fixes failed PRs automatically. Ship in half the time.项目地址: https://gitcode.com/GitHub_Trending/nx/nx创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表