识别与现代形态重写)
Nx 迁移编写避坑指南废弃模式Deprecated Patterns识别与现代形态重写【免费下载链接】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 中迁移migration是nx migrate升级工作区时自动执行的修复脚本负责把用户配置与源码从旧形态改写为新形态。而废弃模式deprecated patterns指两类不该被新代码复制的写法一类只存在于 git 历史中、只能在阅读旧迁移或第三方插件时遇到另一类仍存活在仓库中但被明确禁止复制。本文以 .claude/skills/author-migration/deprecated-patterns.md 为核心骨架结合仓库源码与配套技能文档讲清每一类废弃模式的特征签名recognition signature、为何被废弃以及对应的现代替代写法帮助你迁移或移植旧迁移时直接改写为现代形态而不是照搬。为什么需要一份废弃模式清单Nx 的迁移体系经历了从 Angular Devkit Schematics 到nx/devkit的漫长演进十余年间沉淀了大量历史写法。同一份migrations.json中既有老条目也有新条目git 历史中更埋藏着 v6–v16 各时代的实现。当开发者需要移植某个上游框架自带的迁移到 Nx参照一条旧迁移写新迁移审查第三方插件中的迁移实现最容易犯的错误就是照着历史抄。但历史写法往往依赖已被移除的运行路径例如schematics适配器会丢弃迁移的返回值或者与当前运行时契约runtime-contract.md相冲突。因此 Nx 官方将废弃模式分为两个 registry类别含义适用场景仅存于历史Historical only已从仓库删除运行时会直接失败阅读旧迁移作参考、移植第三方插件时仍存活但禁止复制Still live, do not copy代码还在运行旧条目仍在用编写新迁移时绝不复制需用现代替代无论哪种规则只有一条迁移或引用旧迁移时必须改写为现代形态绝不原样复现。历史遗留模式只存在于 git 历史的写法以下模式已从仓库删除遇到时需识别并整体替换。Angular Devkit Schematic Rulesv6–11 时代特征签名import { Rule, chain } from angular-devkit/schematics配合updateJsonInTree、readJsonInTree、createOrUpdate、带Change对象的insert以及在结尾追加formatFiles()作为 Rule。现代替代默认导出的async function (tree: Tree)统一使用nx/devkit。示例形态见 templates/spec-skeleton.md 中的 spec 骨架——现代迁移直接导入默认导出并调用而非通过 Schematic 的 collection 机制。顶层schematics段2023 年之前特征签名migrations.json中条目挂在schematics键下而非generators。现代替代一律使用generators段。依据 runtime-contract.mdschematics段在运行时走 Angular Devkit 适配器且适配器会完全丢弃迁移的返回值——nextSteps、agentContext全部失效这正是该段被废弃的根本原因。迁移代码内的包版本升级v6–10 时代特征签名在 .ts 实现里调用addUpdateTask(...)、链式RunSchematicTask或通过updateJsonInTree(package.json, ...)直接改版本。现代替代声明式的packageJsonUpdates组只有依赖变更依赖工作区状态条件性变更时才写 .ts 实现。这一点在 SKILL.md 第 1 节有明确规定无条件升级永远不写 .ts 实现条件性依赖变更才使用addDependenciesToPackageJson/removeDependenciesFromPackageJson。workspace.json / angular.json 编辑v8–11 时代特征签名updateWorkspaceInTree、getWorkspace/updateWorkspace、updateBuilderConfig。现代替代项目配置用getProjects/updateProjectConfigurationNx 级配置用readNxJson/updateNxJson。核心原因在 SKILL.md 第 4 节 Config editsgetProjects直接感知项目图且updateProjectConfiguration不会像裸updateJson那样静默跳过基于 package.json 的项目。nrwl/*导入约 v15 之前特征签名from nrwl/workspace、from nrwl/devkit以及readWorkspaceConfiguration/updateWorkspaceConfiguration。现代替代统一nx/devkit。SchematicTestRunner 规格测试v6–13 时代特征签名SchematicTestRunner、UnitTestTree、通过 collection 执行runMigration(name, ...)。现代替代createTreeWithEmptyWorkspace() 直接导入迁移的默认导出。文档特别提醒了一个被丢失的能力旧 helper 通过 migrations.json 按名字加载迁移因此会验证名字 → 实现的接线是否正确而直接导入的 spec 不再做这种校验——这正是为什么 pre-PR 检查清单要求打开 manifest 路径背后的真实文件确认实现指向正确SKILL.md 第 7 节。AI 指令包装工厂2026 年中之前特征签名工厂函数读取files/name.md模板通过tree.write写出tools/ai-migrations/MIGRATE_THING.md并返回string[]。现代替代prompt键直接指向同目录colocate的 .mdrunner 自身会把托管的工作区副本写到tools/ai-migrations/下。即路径写入职责从迁移代码移交给了 runner见 runtime-contract.md 的prompt行。nx/devkit/src/*深路径导入pre-23特征签名from nx/devkit/src/generators/...。现代替代nx/devkit/internal。半公开 helper如forEachExecutorOptions、target-default helper从nx/devkit/internal导入是 SKILL.md 第 4 节 Common canon 的明确要求。仍存活但禁止复制的模式以下写法仍存在于仓库旧条目中运行时也不一定立刻报错但新条目一律禁止复制。cli: nx键特征签名generators 条目内出现cli键旧条目中很普遍。规则死键dead key。依据 runtime-contract.mdcli在按段选择 runner的改造后就已不再使用schema 已标注 No longer used。新条目直接省略。factory键特征签名factory: ./dist/...。规则被容忍的别名。运行时implementation与factory等价且两者同时存在时implementation优先但新条目只写implementation。不要对存量条目做批量改名。packageJsonUpdates 上的x-prompt特征签名x-prompt: Do you want to update...。规则仅交互式生效且已被标记为 Nx v24 移除改用requires做门控。参见 runtime-contract.md 与 templates/migrations-json.md。无 slug 或带点号的条目键特征签名update-22-2-0只有版本、没有动作 slug、16.0.0-remove-nrwl-cli版本段用点号而非连字符、裸版本目录如21-0-0/。规则键名应表达动作无 slug 的键无法区分同一次发布中的两条迁移版本段之间用连字符而非点号目录统一为update-ver/。键的具体形态遵循该文件的主流约定SKILL.md 第 3 节。裸updateJson(tree, nx.json, ...)特征签名直接对 nx.json 调用updateJson。规则改用readNxJson/updateNxJson且仅在内容变化时写回SKILL.md 第 4 节。裸updateJson编辑 project.json特征签名updateJson(tree, join(root, project.json), ...)。规则改用updateProjectConfiguration。裸编辑会静默跳过基于 package.json 的项目——这是项目图统一抽象下最容易踩的坑。返回GeneratorCallback特征签名返回类型为PromiseGeneratorCallback函数返回安装任务。规则runner 会静默丢弃 callbackruntime-contract.md Return values。现代返回值为void | string[] | { nextSteps, agentContext, skipAgentic }安装由 runner 通过 diff package.json 完成绝不返回安装任务、绝不调用installPackagesTask。console.*或 nx 的output工具特征签名console.warn(...)、import { output } from nx/src/utils/output。规则改用 devkit 的logger。原因agentic 运行会捕获 generator 的 logger 输出并喂给验证 agentgenerator_output好的警告应点名文件和剩余工作console.*输出不在该通道内。静态import * as ts from typescript特征签名模块顶部值导入 TypeScript。规则顶部用 type-only 导入import type * as ts from typescript首次使用时惰性ensureTypescript()来自nx/js/internal或ensurePackagetypeof import(typescript)(typescript, *)。这避免在不需要 TypeScript API 的运行中支付加载成本。深层nx/src/*导入特征签名插件迁移里出现from nx/src/utils/...。规则使用 devkit 导出跨边界导入在旧代码中被容忍新代码不允许。例外是packages/nx内部自身使用相对导入。忽略文件的子串检查特征签名content.includes(entry)后字符串拼接。规则改用addEntryToGitIgnore。其实现位于 packages/nx/src/utils/ignore.ts基于ignore包解析而非子串匹配能正确处理已覆盖模式、并自动创建不存在的文件。实际使用范例见 packages/nx/src/migrations/update-23-0-0/add-migrate-runs-to-git-ignore.tsexport default async function addMigrateRunsToGitIgnore(tree: Tree) { if (!tree.exists(.gitignore)) { return; } // Lerna users that dont use nx.json may not expect .nx directory changes if (tree.exists(lerna.json) !tree.exists(nx.json)) { return; } addEntryToGitIgnore(tree, .gitignore, .nx/migrate-runs); await formatChangedFiles(tree); }注意它同时示范了两个通用守卫无.gitignore直接返回Lerna 用户未使用 nx.json 时不写.nx目录。对应条目见 packages/nx/migrations.json 的23-0-0-add-migrate-runs-to-git-ignore。非 colocate 的 prompt 文件特征签名prompt指向某个 generator 的files/目录。规则把 .md 与迁移放在同一update-ver/目录中。依据 runtime-contract.mdprompt相对路径会被校验必须留在 migrations 目录内因此 colocate 是硬性前提。以文档风格编写的 prompt .md特征签名作为prompt接入的文件里出现#### Sample Code Changes这类 h4 标题。规则prompt 使用 runbook 风格模板见 templates/prompt-runbook.mdh4 是documentation文件的体裁。一个典型的 prompt-runbook 包含Overview含 out of scope、Pre-Migration Checklist作用域任务须以 no-op guard 开头、分步 Before/After、Post-Migration Validation 的循环直到变绿、Nx-Specific Notes。迁移中的 devkitglob特征签名从nx/devkit导入的glob(。规则原地弃用deprecated in place改用globAsync。从识别到改写现代迁移的标准形态识别出废弃模式后改写时直接落到现代规范。综合 SKILL.md 与 templates/migrations-json.md现代迁移的标准形态可以概括为三层。文件布局与 manifest 条目packages/plugin/src/migrations/update-major-minor-patch/name.ts packages/plugin/src/migrations/update-major-minor-patch/name.spec.ts 有实现时才需要 packages/plugin/src/migrations/update-major-minor-patch/name.md documentation与 .ts 同名 packages/plugin/src/migrations/update-major-minor-patch/other-name.md prompt基名必须与任何 .ts 不同manifest 中挂generators段路径使用发布形态dist 前缀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 }实现层通则export default async function update(tree: Tree)不接收选项runner 以(tree, {})调用。只用 Tree API绝不使用fs路径用joinPathFragments或node:path的posixhelper 构建。结尾await formatFiles(tree)不触碰 JS/TS/JSON 面时可跳过packages/nx内部用formatChangedFiles。失败开放fail open绝不 throw——一个抛错的迁移会让整个--run-migrations无法恢复无法解析的文件跳过并记录进返回的agentContext。幂等构造重写消耗自身触发条件、写回以updated ! original门控或显式 already-migrated 守卫nx repair会无条件重跑 nx-core 迁移。版本字符串冻结为文件内本地常量绝不从插件的utils/versions导入那些常量随每次发布浮动用户运行的是编译进目标版本的迁移。返回值契约现代迁移的返回值为void | string[] | { nextSteps, agentContext, skipAgentic }string[]是nextSteps的简写nextSteps展示在运行结束摘要与失败回顾中被 Nx Console 持久化但永不进入 agent promptagentContext注入 agent prompt 作为advisory_context在纯人工运行时被丢弃因此面向人的内容必须同步进nextStepsskipAgentic: true声明确定性运行已覆盖一切跳过本会执行的 AI 步骤hybrid 的 prompt 阶段或 generator-only 迁移后的验证步骤仅在迁移能证明无事可做时返回绝不与agentContext同返。新旧形态对照速查废弃模式特征签名现代替代Schematic Rulesangular-devkit/schematics的Rule/chain默认导出async (tree: Tree)顶层schematics段条目在schematics下generators段迁移内升级包addUpdateTask、RunSchematicTask声明式packageJsonUpdates编辑 workspace.jsonupdateWorkspaceInTree等getProjects/updateProjectConfiguration、readNxJson/updateNxJsonnrwl/*导入nrwl/workspace、nrwl/devkitnx/devkitSchematicTestRunner spec按名字runMigrationcreateTreeWithEmptyWorkspace 直接导入默认导出AI 指令工厂读模板 tree.write到tools/ai-migrations/prompt键 runner 自管副本nx/devkit/src/*深路径from nx/devkit/src/...nx/devkit/internalcli: nx条目内cli键省略死键factoryfactory: ./dist/...implementationx-promptpackageJsonUpdates 上的交互提示requires门控无 slug / 点号键update-22-2-0、16.0.0-remove-nrwl-cli动作 slug 连字符版本段裸updateJson(nx.json)直接改 nx.jsonreadNxJson/updateNxJson裸updateJson(project.json)join(root, project.json)updateProjectConfigurationGeneratorCallback返回返回安装任务void/string[]/{ nextSteps, agentContext, skipAgentic }console.*/outputconsole.warn、nx/src/utils/outputdevkitlogger静态 ts 导入顶部import * as tstype-only ensureTypescript()深nx/src/*导入插件迁移里的nx/src/utils/...devkit 导出忽略文件子串检查content.includes(entry)addEntryToGitIgnorepackages/nx/src/utils/ignore.ts非 colocate promptprompt指向 generator 的files/迁移update-ver/目录内 colocate文档体裁 prompth4#### Sample Code Changesrunbook 体裁templates/prompt-runbook.mddevkitglob迁移中的glob(globAsync验证与收尾让改写经得起检查改写完成后用两层机制验证。机械层由仓库 validator 把关npx nx run-many -t test,lint -p plugin跑根级migrations.spec.tsassertValidMigrationPaths校验每条条目路径能在源码树中解析、无孤儿 .ts/.md与nx/nx-plugin-checks校验 manifest 形态、重复键pnpm nx-cloud conformance:check中的migration-markdown-assets规则校验发布形态每个被引用的 .md 确实被打包进构建产物。判断层SKILL.md 第 7 节是 validator 覆盖不到的人工残留确认implementation指向本迁移的文件validator 只查存在性不查指向是否正确确认使用implementation而非factory、无cli键确认版本是该发布轨train的下一个精确预发布版、requires相对落地版本评估且无编码源窗口的上界确认 spec 覆盖全部必测用例negative 必测幂等、畸形输入、多编辑、优先级、列表健全、行为复现按触发条件必测。核心原则始终如一从历史与旧条目中识别模式、改写为现代形态而不是复现它们。【免费下载链接】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),仅供参考