用 Nx migrate 自动化更新依赖:从 package.json 到源码的一站式迁移实战指南
【免费下载链接】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 migrate是 Nx 内置的依赖更新与代码迁移工具:它不仅能自动改写package.json中的依赖版本,还能同步更新 Vite、Playwright、Jest、ESLint 等配置文件,并直接改写你的源码以适配新版本包带来的破坏性变更。本文以 Nx 官方课程 05-automate-updating-dependencies.md 为主线,结合 Nx 官方文档 automate-updating-dependencies.mdoc 与仓库源码实现,带你完整掌握nx migrate的两阶段工作流、--include包选择策略、AI 辅助迁移(agentic flow)以及nx.json全局默认配置,读完即可在自己的工作区中安全、可控地完成一次跨版本升级。
nx migrate 帮你自动化三件事
保持工具链(tooling)时刻更新,是维护任何项目中最繁琐、最耗时的工作之一。Nx 官方课程将nx migrate的核心价值概括为三点:
- 自动更新
package.json依赖:将目标包及其关联包升级到新版本,无需手工改版本号; - 迁移配置文件:例如 Vite、Playwright、Nx 自身的配置,都会按新版本要求的格式被自动改写;
- 调整源码以匹配新版本:跨破坏性变更(breaking changes)时,比如某个 API 改名或某个导入路径变更,迁移会直接修改你的源代码。
只需在项目根目录执行一条命令,Nx 就会以交互方式引导你完成整个更新:
nx migrate从源码看,该命令的入口定义在 command-object.ts:nx migrate [packageAndVersion]既负责"生成迁移文件",也负责"运行迁移",两条子路径由--run-migrations等参数区分。
工作原理:插件声明迁移,Nx 统一收集执行
Nx 知道自己的配置文件位于何处,并确保它们符合预期的格式。这个自动化更新过程通常被称为migration(迁移)。关键在于:每个 Nx 插件都可以为自己擅长的领域提供迁移脚本。
例如 Vite 插件会在跨破坏性变更时提供迁移来更新 Vite 配置文件。当你运行nx migrate时,Nx 会从所有已安装插件中收集待执行的迁移(pending migrations),并把必要的变更应用到工作区。
这一机制在仓库中可以直接验证:
- 每个插件在自己的
migrations.json中声明迁移清单,例如 packages/vite/migrations.json 中就有rename-rollup-options-to-rolldown-options(Vite 8 用 Rolldown 替换 Rollup 后,把vite.config.ts中的rollupOptions重命名为rolldownOptions)这样的真实迁移; - 迁移清单的数据结构定义在 misc-interfaces.ts:一个
MigrationsJson由generators(迁移生成器)、schematics(兼容旧命名)和packageJsonUpdates(依赖版本更新建议)组成,每条迁移条目包含version(适用版本)、implementation(实现文件)、description、可选的prompt(AI 提示文件)等字段。
以 packages/workspace/migrations.json 为例,packageJsonUpdates展示了"推荐依赖升级"的写法——这里 Nx 建议把 TypeScript 从 5.7/5.8 升级到 5.8/5.9,并通过x-prompt向用户确认:
{ "generators": { "23-0-0-move-typescript-compilation-import": { "version": "23.0.0-beta.10", "description": "Rewrites imports of `@nx/workspace/src/utilities/typescript/compilation` to `@nx/js/internal`, where the module now lives.", "implementation": "./dist/src/migrations/update-23-0-0/move-typescript-compilation-import" } }, "packageJsonUpdates": { "21.5.0": { "version": "21.5.0-beta.2", "x-prompt": "Do you want to update to TypeScript v5.9?", "requires": { "typescript": ">=5.8.0 <5.9.0" }, "packages": { "typescript": { "version": "~5.9.2", "alwaysAddToPackageJson": false } } } } }可以看到:迁移是按version精确锚定的,requires字段限定了适用前提(如typescript >=5.8.0 <5.9.0),只有满足条件时这条更新建议才会被纳入本次迁移。
迁移的两阶段工作流:先生成,再运行
更新 Nx 工作区分为两个阶段,这也是理解整个nx migrate的关键:
- Generate(生成):
nx migrate把包版本更新应用到package.json,并写出一个migrations.json文件。此时不触碰任何源码。 - Run(运行):
nx migrate --run-migrations运行上一步生成的迁移,更新配置文件与源码。
两阶段之间你可以随时介入,针对自己的具体工作区做出调整——在大代码库中,这种"生成与执行分离"的设计让你能够更精细地控制变更范围。
Step 1:生成迁移
运行migrate命令并按提示操作:
nx migrateNx 会解析最新版本,并且当本次更新跨越超过一个大版本(major version)时,询问你想一次跳多远。官方建议并推荐最稳妥的方式是一次只升级一个大版本(详见 advanced-update.mdoc 中 "One major version at a time" 一节:先升级到当前大版本的最新版,运行迁移,再进入下一个大版本,如此往复)。
Nx 还会询问要迁移哪些包版本,该答案对应--include参数:
required—— 目标包及其随附的包。例如 Nx 本身及其插件(如@nx/vite);optional—— 这些包推荐的依赖更新。例如vite本身(而非@nx/vite);all—— 以上两者全部包含。
拿不准时选required。只更新 Nx 及其插件可以让 PR 变更范围更小、出问题的概率更低,这在大型工作区尤为重要。之后再用nx migrate --include=optional补齐其余更新;如果你接受在一个 PR 里完成所有事,就用--include=all。
有些情况下你还可以把"optional 补课"限定到单个插件的依赖,例如nx migrate @nx/vite --include=optional(关于该用法的注意事项,见 advanced-update.mdoc 中 "Choosing which packages to migrate" 一节:部分插件更新依赖其他插件先执行更新,如@nx/angular有时需要@nx/js的 TypeScript 更新,因此拿不准时建议直接跑完整的nx migrate --include=optional)。
生成阶段结束后你会得到:
package.json已写入新版本号;migrations.json已生成(仅当存在待执行迁移时)。
此时尚未安装任何包,也没有触碰其他文件。
接下来先检查package.json,确认改动是否合理——有时迁移会把某个包升到不被允许的版本,或与另一个包产生冲突,你可以在安装前自由调整版本号。确认无误后,按你的包管理器安装依赖:
npm installyarn installpnpm installbun install同时,打开migrations.json看看将要应用哪些迁移。如果该文件不存在,说明没有需要运行的迁移。
Step 2:运行迁移
执行上一步生成的迁移:
nx migrate --run-migrations一条迁移里有什么?
迁移逐条运行,包含两种类型的变更:
- 基于生成器(Generator-based,又称 script-based):程序化的配置或代码变更。例如 Vite 8 中把
vite.config.ts的rollupOptions改为rolldownOptions——这正是 packages/vite/migrations.json 中rename-rollup-options-to-rolldown-options所做的事。 - 基于提示(Prompt-based):AI 辅助的变更。这类变更无法用确定性规则表达,需要针对你的具体代码做判断。
一条迁移可以是纯生成器、纯提示,也可以是混合型(先跑生成器、再由 AI 辅助完成剩余变更)。
运行过程
- 纯生成器迁移会自动运行,所有改动处于未暂存(unstaged)状态,供你审阅。
- 当队列中出现纯提示或混合型迁移、且系统安装了受支持的 AI Agent(Claude Code、OpenAI Codex 或 OpenCode)时,Nx 会询问是否继续 agentic 流程。你可以选择仅本次生效,也可以让 Nx 在
nx.json中记住你的选择。
开启 agentic 流程后:
- 先生成器式变更,再由 Agent 校验结果;
- 然后 Agent 按提示指令应用基于提示的变更;
- 每条迁移都会单独创建一个 git commit,这样 Agent 可以在隔离的 diff 中审阅每条迁移的改动。
如果没有 Agent,纯生成器迁移以及混合型迁移的生成器部分仍然会运行;被跳过的提示文件会按顺序列在 next-steps 输出中,方便你手动处理。
在 AI Agent 的终端内运行时:如果你在某个 AI Agent 的终端里执行
nx migrate --run-migrations,Nx 会把基于提示的迁移委托给该 Agent,而不是再派生一个新的 Agent。
迁移是版本特定的:每个 Nx 插件只提供与特定版本相关的迁移。生成的
migrations.json只包含适用于你当前这次升级的迁移。
从源码看,agentic 流程由 packages/nx/src/command-line/migrate/agentic 目录下的模块实现,提示文件则统一存放在工作区的tools/ai-migrations目录(见 prompt-files.ts 中的AI_MIGRATIONS_DIR定义)。每个 Agent 的可选值(claude-code、codex、opencode)与参数校验规则定义在 command-object.ts。
Step 3:清理
运行完所有迁移后,可以删除migrations.json并提交剩余改动。
需要注意的是:建议保留migrations.json直到所有在迁移前创建的分支都合并完毕。保留该文件可以让其他开发者运行nx migrate --run-migrations,把同样的迁移流程应用到他们新合并的代码上。
Step 4:更新社区插件(可选)
如果你安装了 Nx 社区插件,需要逐个迁移它们(前提是它们提供了迁移脚本):
nx migrate my-plugin查看当前安装了哪些插件,运行:
nx report在 nx.json 中配置 migrate 默认值
与其每次运行都重复传相同的参数,不如在工作区nx.json的migrate段中设置全局默认值。你可以控制提交行为、包选择、跨多版本处理方式以及 agentic 流程:
// nx.json { "migrate": { "agentic": "claude-code", "createCommits": true, "commitPrefix": "chore(repo): apply nx migration " } }该配置项的类型定义在 nx-json.ts 的NxMigrateConfiguration中,支持的选项包括:
| 配置项 | 等价参数 | 说明 | 默认值 |
|---|---|---|---|
createCommits | --create-commits/-C | 每条迁移运行后自动创建 git commit | false |
commitPrefix | --commit-prefix | 迁移 commit 的消息前缀 | chore: [nx migration] |
include | --include | 限制迁移哪些包:required/optional/all | all |
multiMajorMode | --multi-major-mode | 跨多个大版本时的处理方式:direct直达目标 /gradual先升到最小推荐步骤 | 交互式询问 |
agentic | --agentic | agentic 流程默认值:false关闭、true自动解析已安装 Agent、或指定"claude-code"/"codex"/"opencode" | 交互式询问 |
validate | --validate/--no-validate | agentic 流程开启时,是否对纯生成器迁移做 Agent 驱动的校验 | true |
useRegistryResolution | — | 是否通过 npm registry 解析版本(更快),环境变量NX_MIGRATE_USE_REGISTRY_RESOLUTION可覆盖 | true |
默认值的合并逻辑在 migrate-config.ts 的applyNxJsonMigrateDefaults中实现,遵循命令行参数 > 环境变量 > nx.json > 内置默认值的优先级。例如multiMajorMode对应的NX_MULTI_MAJOR_MODE环境变量会优先于nx.json中的配置。
完整的nx.json配置参考见 reference/nx-json.mdoc。
保持所有 Nx 包版本同步
运行nx migrate时,nx包和所有@nx/包会被更新到相同版本。保持这些版本同步对 Nx 正常工作至关重要(具体原因和排查方法见 keep-nx-versions-in-sync.mdoc)。
只要坚持用nx migrate而不是手工改版本号,你就不用担心同步问题。另外,安装新插件时请使用nx add <plugin>,它会自动安装与你仓库中 Nx 版本匹配的插件版本。官方插件的迁移生成器设计为幂等的(重复运行等价于运行一次),因此即使迁移中途重跑也不必担心重复应用。
需要更多控制?高级更新技巧
当你需要偏离默认行为时——比如先跳过可选包更新、锁定或禁用某个 AI Agent、逐条运行迁移、或通过修改migrations.json跳过某条迁移——可以参考 Advanced Update Process 指南。其中几个高频场景如下:
逐条提交便于审阅。大型升级(尤其是跨大版本)会产生大量改动,难以区分哪些是自动生成、哪些是手工调整。使用--create-commits让每条迁移单独成 commit:
nx migrate --run-migrations --create-commits默认 commit 前缀是chore: [nx migration],可用--commit-prefix自定义:
nx migrate --run-migrations --create-commits --commit-prefix="chore(core): AUTOMATED - "手工调整migrations.json。两阶段分离的价值在大项目中尤为明显:你可以注释掉、重排、跳过某条迁移,甚至让同一条迁移跑多次(比如长迁移过程中 rebase 之后)。自定义迁移文件路径:
nx migrate --run-migrations=migrations.json覆盖版本。想用与 Nx 推荐不同的包版本时:
nx migrate --to="jest@30.0.0,cypress@15.0.0"注意:选择 Nx 未测试过的组合可能引入意外问题;升级最好在干净的 git 历史中进行,失败时可用git reset --hard与git clean -fd回滚(使用--create-commits时需回退到第一条自动迁移 commit 之前的 SHA)。
小结
nx migrate把"升级依赖"从手工劳动变成了一条可复现、可分阶段控制、可审阅的命令流:生成(Generate)→ 检查 → 安装 → 运行(Run)→ 清理。插件生态通过migrations.json声明各自领域的迁移(Vite、Workspace 都是现成范例),Nx 负责收集并按版本精确执行;对无法确定性表达的破坏性变更,还能借助 Claude Code、Codex 或 OpenCode 以 agentic 流程辅助完成。配合nx.json的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),仅供参考