前言
近期将公司的新 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
的目标是将过程自动化到某个程度,然后让开发者接手剩下的部分,使他们能够掌控迁移过程,执行后会启动以下流程:
- 触发对本地工作环境的分析,以确定需要更新的套件。
- 更新
package.json
中的版本,但不会安装它们。 - 生成一个
migration.json
文件,其中包含需要执行的脚本指针,以将代码和配置文件自动化迁移到新版本。
到这里升级过程将暂停,允许开发者检查并在需要时调整对 package.json
的更改以及 migrations.json
的内容,如果 OK 就继续:
npm install
以及执行自动迁移脚本:
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
並在各自的環境中進行更新後再合併,降低支線之間的差異造成的升級困難。