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 並在各自的環境中進行更新後再合併,降低支線之間的差異造成的升級困難。

延伸閱讀