Nx 迁移实战:自动升级 Gradle 插件 dev.nx.gradle.project-graph 至 0.1.10
2026/9/11 2:18:16 网站建设 项目流程

Nx 迁移实战:自动升级 Gradle 插件 dev.nx.gradle.project-graph 至 0.1.10

【免费下载链接】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 的@nx/gradle插件通过迁移机制自动维护build.gradle(.kts)dev.nx.gradle.project-graph插件的版本。本文以仓库中 22-2-0 版本迁移说明 为骨架,深入解析这条迁移在何时触发、改动了哪些文件、如何兼容 Groovy/Kotlin DSL 与 Gradle Version Catalog 的多种写法,并结合源码实现与测试用例给出可复现的验证方式。读完你既能理解nx migrate背后的自动升级原理,也能独立完成该插件版本的手动升级与校验。

一、这条迁移解决什么问题

dev.nx.gradle.project-graph是 Nx 为 Gradle 工作区提供的官方插件,负责将 Gradle 的项目与任务信息导出为 JSON,供 Nx 构建项目图谱(Project Graph)使用。其安装方式如下(引自 插件 README):

// build.gradle (Groovy DSL) plugins { id "dev.nx.gradle.project-graph" version "+" }
// build.gradle.kts (Kotlin DSL) plugins { id("dev.nx.gradle.project-graph") version("+") }

插件版本会随 Nx 版本演进迭代。当 Nx 升级到 22.2.0 时,需要把工作区中该插件的版本统一提升到0.1.10,以保证项目图谱生成逻辑与新版 Nx 兼容。这一升级正是由 change-plugin-version-0-1-10 迁移 自动完成的。

在 migrations.json 中,这条迁移被注册为:

"change-plugin-version-0-1-10": { "version": "22.2.0-beta.4", "cli": "nx", "description": "Change dev.nx.gradle.project-graph to version 0.1.10 in build file", "factory": "./dist/src/migrations/22-2-0/change-plugin-version-0-1-10", "documentation": "./dist/src/migrations/22-2-0/change-plugin-version-0-1-10.md" }

也就是说,当工作区从旧版本 Nx 迁移到22.2.0-beta.4 及以上版本时,这条迁移会被纳入执行队列。

二、迁移前后的文件变化

官方迁移说明 给出了最直观的变更示例——在build.gradleplugins块中把插件版本号从0.1.0提升为0.1.10

迁移前(Before):

plugins { id "dev.nx.gradle.project-graph" version "0.1.0" }

迁移后(After):

plugins { id "dev.nx.gradle.project-graph" version "0.1.10" }

注意,这里展示的是Groovy DSL的写法。实际上迁移对Kotlin DSL同样生效,最终效果等价于:

// build.gradle.kts 迁移后 plugins { id("dev.nx.gradle.project-graph") version("0.1.10") }

两种 DSL 的差异(引号风格、id是否带括号、version是否带括号)都由底层实现的正则与分支逻辑分别处理,详见下文源码解析。

三、迁移实现解析:它到底改了什么

迁移入口实现 的核心逻辑非常清晰,分三步执行:

export default async function update(tree: Tree) { const nxJson = readNxJson(tree); if (!nxJson) { return; // 1. 无 nx.json,直接跳过 } if (!hasGradlePlugin(tree)) { return; // 2. 未启用 @nx/gradle,直接跳过 } const gradlePluginVersionToUpdate = '0.1.10'; // 3a. 用 AST 方式更新 Version Catalog(保留原格式) await updateNxPluginVersionInCatalogsAst(tree, gradlePluginVersionToUpdate); // 3b. 更新 build.gradle(.kts) 文件 await addNxProjectGraphPlugin(tree, gradlePluginVersionToUpdate); }

1. 守卫条件:只在合理的场景下执行

迁移不是无条件执行的,它先通过两个守卫条件判断当前工作区是否需要升级:

  • 必须存在nx.json:这是 Nx 工作区的标志性配置文件,缺失说明这不是一个可被 Nx 管理的仓库。
  • 必须启用了@nx/gradle插件:判断逻辑在 has-gradle-plugin.ts 中,即检查nx.jsonplugins数组里是否包含@nx/gradle(支持字符串写法或{ plugin: '@nx/gradle' }对象写法):
export function hasGradlePlugin(tree: Tree): boolean { const nxJson = readNxJson(tree); return !!nxJson.plugins?.some((p) => typeof p === 'string' ? p === '@nx/gradle' : p.plugin === '@nx/gradle' ); }

这两个条件缺一不可,测试用例也明确验证了"无 nx.json"与"未启用 Gradle 插件"两种场景下迁移应保持文件不动(见 change-plugin-version-0-1-10.spec.ts)。

2. 两条升级路径:Version Catalog 优先,build.gradle 兜底

迁移的升级动作分为两条并行的路径:

  • updateNxPluginVersionInCatalogsAst:扫描工作区中所有**/gradle/*.versions.toml文件,用 TOML AST 解析并精准替换版本号;
  • addNxProjectGraphPlugin:定位每个settings.gradle(.kts)旁边的build.gradle(.kts),更新其中直接声明的插件版本。

之所以先更新 Version Catalog 再更新 build.gradle,是因为后者的逻辑需要感知前者——如果插件是通过 Catalog 别名(alias)引入的,build.gradle 中就不该再出现内联版本号,也就不需要(也不应该)追加allprojects传播块。

3. 保持格式的 Version Catalog 更新

Version Catalog(libs.versions.toml)是 Gradle 集中管理依赖与插件版本的机制,格式化要求较高。为此,迁移没有采用简单的文本替换,而是使用toml-eslint-parser将 TOML 解析为 AST,只对版本值所在的区间做精确替换,再按原文本重建内容(见 version-catalog-ast-utils.ts 的reconstructTomlWithUpdates)。这样注释、缩进、引号风格等格式都能原样保留。

该工具函数支持三种 Catalog 中声明插件的方式(见 version-catalog-ast-utils.ts 的findPluginConfig):

Catalog 写法示例迁移结果
简单格式("插件ID:版本"nx-graph = "dev.nx.gradle.project-graph:0.0.1"nx-graph = "dev.nx.gradle.project-graph:0.1.10"
内联对象(直接写版本)nx-graph = { id = "dev.nx.gradle.project-graph", version = "0.0.1" }version = "0.1.10"
引用版本(version.ref[versions]nx-project-graph = "0.0.1"+[plugins]version.ref = "nx-project-graph"[versions]中对应条目更新为"0.1.10"

对于version.ref引用写法,迁移会顺着引用链找到[versions]表中的真实版本条目并更新它,而不是去改version.ref本身。上述三种写法在 change-plugin-version-0-1-10.spec.ts 中都有对应的测试覆盖。

4. build.gradle(.kts) 中的版本更新

对于直接内联声明插件的build.gradle(.kts),更新逻辑位于 gradle-project-graph-plugin-utils.ts。其核心是一个兼容两种 DSL 的正则:

// 兼容 id "plugin" version "x" 与 id("plugin") version("x") const regex = /(id\s*\(?["']dev\.nx\.gradle\.project-graph["']\)?\s*version\s*\(?["'])([^"']+)(["']\)?)/;

命中后直接执行content.replace(regex,$1${newVersion}$3),只替换中间版本号部分;若未命中(例如插件是通过 Catalog 别名引入的),则打印Please update plugin dev.nx.gradle.project-graph to 0.1.10警告,不破坏文件。

值得一提的还有 addNxProjectGraphPluginToBuildGradle 的幂等处理:如果build.gradle已存在plugins块就直接补充声明,不存在则新建plugins块;同时会把插件通过allprojects { apply ... }传播到所有子项目,且重复执行不会追加重复声明。

四、如何运行这条迁移

迁移本身不要求手动编辑任何文件,而是随 Nx 的标准升级流程执行:

  1. 在 Nx 工作区根目录运行nx migrate @nx/gradle@latest(或指定目标版本),Nx 会依据 migrations.json 计算出从当前版本到目标版本之间需要执行的全部迁移;
  2. 生成迁移计划后运行nx migrate --run-migrations执行它们,其中就包含change-plugin-version-0-1-10
  3. 执行完成后,检查build.gradle/build.gradle.kts以及各gradle/libs.versions.tomldev.nx.gradle.project-graph的版本已变为0.1.10

如果你不想等待下一次升级流程,也可以完全手动升级:按本文第二节的 Before/After 示例修改插件版本号,或编辑libs.versions.toml中对应的版本条目。

五、迁移后的验证

升级是否成功,可从两个层面验证。

1. 直接查看文件内容

迁移的核心断言在测试中体现得十分明确:以 Groovy DSL 测试 为例,迁移后文件必须包含version "0.1.10"不包含旧版本"0.0.1"。对 Kotlin DSL、多模块多build.gradle、Catalog 与 build.gradle 同时存在等场景,spec.ts 中均有对应的断言,可作为你人工核对文件时的参照。

2. 运行插件验证功能

升级只是手段,最终目的是让项目图谱功能正常工作。按 插件 README 的说明,可在工作区执行:

./gradlew nxProjectGraph

正常输出类似:

> Task :nxProjectGraph < your workspace >/build/nx/add-nx-to-gradle.json

该命令会在build/nx/add-nx-to-gradle.json生成一份包含nodesdependenciesexternalNodes的 JSON,供 Nx 消费构建项目图谱。如果迁移后该命令仍能正常产出 JSON,说明 0.1.10 插件版本已生效且与当前 Nx 版本匹配。

六、版本演进:一次常规但必须执行的升级

从仓库的迁移目录(packages/gradle/src/migrations)可以看到,dev.nx.gradle.project-graph的版本升级是一条反复出现的迁移主题:从 21-1-2 的0.1.0、21-3-0 的0.1.2,一路到 22-2-0 的0.1.10、23-2-0 的0.1.25。这说明了两个事实:

  • 插件版本与 Nx 版本是强绑定关系,Nx 每次发布都会同步推进 Gradle 插件的版本号;
  • 当前仓库 versions.ts 中维护的期望版本为0.1.250.1.10只是 22.2.0 时间节点上的中间版本,后续升级流程会继续沿用同一套迁移框架自动推进。

理解0.1.10这条迁移,等于掌握了整个插件版本迁移家族的通用原理:守卫条件 + AST 保格式的 Catalog 更新 + 幂等的 build.gradle 更新。下次遇到change-plugin-version-0-1-x系列迁移,你都能用同样的方法分析和验证。

相关文件索引

  • 迁移说明:change-plugin-version-0-1-10.md
  • 迁移实现:change-plugin-version-0-1-10.ts
  • 测试用例:change-plugin-version-0-1-10.spec.ts
  • 迁移注册表:migrations.json
  • 插件启用判断:has-gradle-plugin.ts
  • build.gradle 更新逻辑:gradle-project-graph-plugin-utils.ts
  • Version Catalog AST 工具:version-catalog-ast-utils.ts
  • 插件版本常量:versions.ts
  • Gradle 插件安装与用法:project-graph/README.md

【免费下载链接】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),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询