Nx Migrate to Solve Upgrade Problem

来看看 Nx 如何解决套件框架更新的问题 - nx migrate

前言

近期将公司的新 Nx Monorepo 架构项目通过 GitHub Action 添加了自动更新套件的功能,会想实践该功能是因为旧项目疏于更新导致吃了非常多的苦头,所以希望在新架构下可以有更轻松且自动化的方式去执行更新依赖套件与框架的动作。

其中 Nx 有专属的 nx migrate 指令帮助我们达成这件事,并且背后有些非常有趣的机制与理念。

开发者应与时俱进,这不跟产品长期目标相违背

开发者喜欢接触闪亮的新事物,因为通常能够带来更高的生产力与更好的开发体验,在实验性 Side-Project 总是用饱用满,但在真实工作环境却总是遇到各式各样的阻碍,逐渐放弃跟上新技术的脚步。

我们总是将升级维护的工作安排到最低的优先级,这是合情合理的决定,毕竟产品的核心目标就是满足用户需求而不是让开发者们开心,但这之间的关系是相辅相成的。

并不是要断定「新事物」绝对比「旧事物」好,而是新事物通常会带来新的思维与解决问题的方案让功能能够用更优雅的方式去搭建,特别在前端生态圈是不可避免的。

当你停滞更新技术,未来升级将花费更多成本面对更大的挑战

让工具长青 (Evergreen)

要让手边的工具不生锈过时最好的办法就是持续频繁的将大大小小的更新通过简单的方式去执行,我在使用 Nx 时有发现他们正尽力去降低版本迭代的痛点:

  • Nx 向 Angular 借鉴了 ng update 的概念提供了 nx migrate,不仅自动更新 npm 包,还在发生重大变更时运行迁移脚本以将代码和配置文件迁移到新版本。
  • 尽量推崇 Single Version Policy🔗 来确保整个项目中的套件都是同一个版本,避免不同版本之间的相容性问题。

Nx 的多步骤更新

举例来说如果在大型 Repo 上工作(甚至可能在 Monorepo 中),可能有无数的 PR 等待合并……那么迁移需要与开发势必会需要同时进行,Nx 有考虑到这样的问题并提供了解决方案: nx migrate

nx migrate 的目标是将过程自动化到某个程度,然后让开发者接手剩下的部分,使他们能够掌控迁移过程,执行后会启动以下流程:

  1. 触发对本地工作环境的分析,以确定需要更新的套件。
  2. 更新 package.json 中的版本,但不会安装它们。
  3. 生成一个 migration.json 文件,其中包含需要执行的脚本指针,以将代码和配置文件自动化迁移到新版本。

到这里升级过程将暂停,允许开发者检查并在需要时调整对 package.json 的更改以及 migrations.json 的内容,如果 OK 就继续:

Terminal window
npm install

以及执行自动迁移脚本:

Terminal window
nx migrate --run-migrations=migrations.json

迁移脚本看起来像是这样:

{
"migrations": [
{
"version": "11.0.0-beta.0",
"description": "Rename emotion packages to match new 11.0.0 package names",
"factory": "./src/migrations/update-11-0-0/rename-emotion-packages-11-0-0",
"package": "@nrwl/react",
"name": "rename-emotion-packages-11.0.0"
},
{
"version": "11.0.0-beta.0",
"description": "Update libraries",
"factory": "./src/migrations/update-11-0-0/update-11-0-0",
"package": "@nrwl/react",
"name": "update-11.0.0"
},
{
"version": "10.2.1-beta.1",
"description": "Adjusts the tsconfig mapping",
"factory": "./src/migrations/update-10-2-1/update-10-2-1",
"package": "@nrwl/storybook",
"name": "update-10.2.1"
},
{
"version": "10.3.1-beta.1",
"description": "Add missing storybook config to lint target",
"factory": "./src/migrations/update-10-3-0/update-10-3-0",
"package": "@nrwl/storybook",
"name": "update-10.3.1"
},
{
"version": "11.0.12",
"description": "Update storybook if installed and above 6",
"factory": "./src/migrations/update-11-0-12/update-storybook",
"package": "@nrwl/storybook",
"name": "update-11-0-12"
}
]
}

這麼做的好處是 nx migrate --run-migrations=migrations.json 允許被多次執行,當需要橫跨不同分支去遷移專案整體版本時就非常有用,所有 PR 和分支都可以與最新的主幹進行 rebase 獲取 migrations.json 並在各自的環境中進行更新後再合併,降低支線之間的差異造成的升級困難。

延伸閱讀