iT邦幫忙

2024 iThome 鐵人賽

DAY 20
0
自我挑戰組

讓我們一起與turboRepo共舞系列 第 20

Monorepo: 一個倉庫統治所有代碼的神奇魔法

  • 分享至 

  • xImage
  •  

在現代軟體開發中,Monorepo 已成為團隊協作與代碼管理的重要策略。本文將探討 Monorepo 的優缺點,並分享團隊如何運用 Monorepo(特別是 Turborepo)來解決實際開發中的痛點。

Monorepo 的優缺點
優點

  • 可見性:所有團隊成員都能看到彼此的代碼,促進跨團隊協作,任何人都可以協助修復 Bug。
  • 一致性:統一的代碼庫使得執行代碼品質標準和風格更容易,保持代碼風格的一致性。
  • 共享時間軸:共享的專案或 API 變更會立即被揭露,團隊可以快速跟進變更或使用新功能。
  • 共享性:相同的代碼可以抽離成獨立項目,供其他項目共同使用(如 UI 函式庫、工具類等)。
  • 原子提交:開發人員可以在一次提交中更新多個套件或專案,保持變更的一致性。
  • 微前端友好:對於微前端專案,Monorepo 能更好地管理和協調各個組件。
    缺點
  • 性能問題:隨著代碼庫的增大,命令和 IDE 的響應速度可能變慢。
  • 破壞性風險:一個修改可能影響全局,若沒有嚴格的測試,可能導致多個項目出現 Bug。
  • 學習曲線:開發人員需要適應 Monorepo 的架構,理解多個緊密耦合專案的依賴關係。
  • 權限控制:難以對單個項目進行細粒度的權限管理。
  • 代碼審查複雜度:同時修改多個項目時,代碼審查的難度和複雜度增加。
  • 團隊遇到的痛點 在實際的專案開發中,我們團隊遇到了以下問題:
    • 專案孤立:團隊以專案為導向,每個專案都有獨立的倉庫,新舊專案之間相互獨立,無法重複使用已有的功能和代碼。
    • 經驗無法積累:從項目中積累的經驗未能提煉,共享給其他專案,導致重複工作。
    • 組件無法共享:封裝的組件無法在不同項目間共用,缺乏統一的組件文檔。
    • 重複開發:使用微前端架構時,相同的網路請求、工具類別、佈局元件等需要在每個專案中重新開發。
    • 新專案啟動慢:開始新專案時,需要從舊專案中複製基本功能,效率低下。

Turborepo 如何解決痛點
為了解決上述問題,我們採用了 Turborepo,並取得了顯著的效果:

抽離共用功能:將一些通用能力(如流程編排、動態表單)抽離成獨立項目,其他項目可直接引入使用,減少重複開發。
建立 UI 庫:構建統一的 UI 庫項目,應用項目可直接引入使用,並提供完整的文檔,提升開發效率。
共享工具類:將網路請求、工具類、加密等抽離成獨立項目,供其他項目重複使用,保持代碼一致性。
為何選擇 Turborepo
快取機制:Turborepo 具有強大的快取功能,能夠快取任務的結果和日誌,提升構建速度。
任務並行執行:優化了任務的並行執行,充分利用 CPU 資源,加快構建流程。
官方推薦:由於專案使用了 umijs 作為腳手架,其官方推薦使用 Turbo 的快取機制。
Turborepo 基本介紹
Turbo 的特性
快取任務
評估任務輸入:將工作區資料夾中所有非 Git 忽略的檔案轉換成哈希值。
檢查快取:查看本機快取中是否存在相同哈希值的快取資料夾。
執行或復用任務:若無快取,則執行任務並快取結果;若有快取,直接復用結果,省略執行時間。
平行任務
Turbo 在執行指令時,會利用所有可用 CPU,平行執行多個任務。

工作區與任務關係
工作區:每個應用程式和軟體包都在自己的工作區中,擁有自己的 package.json。
根工作區:根資料夾下的 package.json 用於指定整個 Monorepo 的依賴項,並新增運行在整個 Monorepo 上的任務。
Turborepo 的使用
宣告 Pipeline
在 turbo.json 中,最重要的是 pipeline 配置,用於聲明工作區的任務及任務之間的依賴關係,並可配置任務的快取。例如:

{
  "$schema": "https://turbo.build/schema.json",
  "pipeline": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": [".next/**", "!.next/cache/**", ".svelte-kit/**"]
    },
    "test": {
      "dependsOn": ["build"],
      "inputs": ["src/**/*.tsx", "src/**/*.ts", "test/**/*.ts", "test/**/*.tsx"]
    },
    "lint": {},
    "deploy": {
      "dependsOn": ["build", "test", "lint"]
    }
  }
}

配置任務之間的依賴關係
在同一工作區
若工作區的任務依賴目前工作區的其他任務,可使用:

{
  "dependsOn": ["build"]
}

例如,執行 test 任務之前需要先執行當前工作區的 build 任務。

在不同工作區
使用 ^ 符號來聲明任務依賴其所依賴的工作區中的任務:

{
  "dependsOn": ["^build"]
}

表示 build 任務需要先完成其所依賴工作區的 build 任務。

依賴特定工作區的任務
語法為 #,例如:

{
  "$schema": "https://turbo.build/schema.json",
  "pipeline": {
    "frontend#deploy": {
      "dependsOn": ["ui#test", "backend#deploy"]
    }
  }
}

表示 frontend 工作區的 deploy 任務需要在 ui 的 test 和 backend 的 deploy 任務完成後執行。

運行根節點任務
執行 Monorepo 根目錄 package.json 中的任務,語法為 "//#"。

注意事項
如果 pipeline 中聲明的任務在所有工作區的 package.json 中不存在,Turbo 會優雅地忽略這些任務,不會報錯。
pipeline 是唯一聲明 Turbo 任務的地方,未在 pipeline 中聲明的任務,執行會報錯。


上一篇
MonoRepo 整理文章
下一篇
深入探討 Turborepo 快取配置:提升 Monorepo 開發效率的秘訣
系列文
讓我們一起與turboRepo共舞30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言