Turborepo logo

從 Nx 遷移

本指南將協助您將現有的 Nx 儲存庫遷移到 Turborepo。

  • 透過從 Nx starter 遷移到 Turborepo 來探索關鍵概念
  • 更複雜遷移情境的考量

為何切換?

您可能有很多理由選擇從 Nx 遷移到 Turborepo。以下,我們列出了開發人員在遷移時最常提及的動機。

使用生態系統標準

Turborepo 的目標是輕量化,並以您的儲存庫作為事實來源。Turborepo 建構於 JavaScript 套件管理器工作區之上以支援 JavaScript/TypeScript 就是一個例子。

相比之下,Nx 使用外掛程式、依賴項和其他 Nx 特有程式碼的層層疊疊來推斷有關您儲存庫的資訊。雖然這些外掛程式可以提供一層功能並且是可選的,但希望遷移的 Nx 使用者經常將從其程式碼庫中移除 Nx 特有程式碼作為其變更的主要動機。

更佳的原始碼控制

Nx 的理念涉及使用外掛程式、依賴項和 Nx 特有程式碼層層包裝您的程式碼。雖然這些程式碼層是可選的,但它們提供了 Nx 的大部分價值,並且 Nx 建議使用它們,因此大多數 Nx 儲存庫都具有這些層。遷移到 Turborepo 時,許多開發人員解釋說,這些層往往會建立一層混淆,將其儲存庫從其控制中抽離出來,從而導致問題。

Turborepo 選擇讓您按照自己的方式處理您的工具,隨心所欲地設定(或不設定)您的任何工具。

更少的儲存庫管理器設定

遷移到 Turborepo 可能需要刪除您先前為 Nx 所做的設定,並以更少的 Turborepo 設定取而代之,因為 Turborepo 會自動推斷您儲存庫的需求。例如,以下是您在下面使用的 Turborepo 和 Nx 的等效 starter 中找到的工具特定設定。

turbo.json
{
  "$schema": "/schema.json",
  "ui": "tui",
  "tasks": {
    "build": {
      "dependsOn": ["^build"],
      "inputs": ["$TURBO_DEFAULT$", ".env*"],
      "outputs": [".next/**", "!.next/cache/**"]
    },
    "lint": {
      "dependsOn": ["^lint"]
    },
    "check-types": {
      "dependsOn": ["^check-types"]
    },
    "dev": {
      "cache": false,
      "persistent": true
    }
  }
}

免費遠端快取

Turborepo 的遠端快取將您的任務結果儲存在雲端伺服器上。這透過防止整個組織內重複的工作來節省大量時間。到目前為止,Vercel 遠端快取已為團隊節省了超過 500 年的運算時間。

自 Nx 19.7 以來,即使是自行託管,類似的功能也是付費功能。當自行託管或使用 Vercel 遠端快取時,Turborepo 的遠端快取是免費的。

遷移步驟

我們這次遷移的目標是盡快獲得可運作的 Turborepo 任務,以便您可以逐步採用 Turborepo 功能。我們將從使用 Nx scaffolder 建立具有 Next.js 應用程式的儲存庫開始。

終端機
npx create-nx-workspace --preset=next --ci=skip --e2eTestRunner=none --style=tailwind --nextAppDir=true --nextSrcDir=false --packageManager=pnpm --appName=starter

步驟 1:更新 .gitignore

Turborepo 使用 .turbo 目錄來保存本機快取和有關您儲存庫的其他資訊。因此,應將其新增至您的 .gitignore。

.gitignore
.turbo

步驟 2:新增工作區定義

Turborepo 建構於套件管理器工作區之上,這是 JavaScript 生態系統標準。將目錄路徑新增至將包含套件的工作區。

package.json
{
  "workspaces": ["apps/*"]
}

步驟 3:將 package.json 新增至應用程式

Turborepo 使用標準 package.json 檔案,而不是新增其他設定檔(如 project.json)。

將 package.json 新增至 starter 應用程式。在 ./apps/starter/package.json 建立包含 dev 和 build 指令碼的 package.json。

./apps/starter/package.json
{
  "name": "starter",
  "scripts": {
    "dev": "next dev",
    "build": "next build"
  }
}

步驟 4:移除 Nx 外掛程式

從 ./apps/starter/next.config.js 移除 Nx 外掛程式。下面的範例檔案沒有設定,但您現有的 Next.js 應用程式可能需要一些設定。

./apps/starter/next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {};
 
module.exports = nextConfig;

步驟 5:新增 packageManager 欄位

根 package.json 需要具有 packageManager 欄位。這可確保儲存庫中的開發人員使用正確的套件管理器,並且 Turborepo 可以根據您的 lockfile 優化您的套件圖。

./package.json
{
  "packageManager": "npm@10.0.0"
}

步驟 6:執行套件管理器的安裝命令

透過執行安裝命令來更新您的 lockfile。

終端機
npm install

完成此操作後,您應該會看到 lockfile 差異,表明套件已新增至套件管理器的工作區。

步驟 7:安裝 Turborepo

將 Turborepo 新增至工作區的根 package.json。

終端機
npm install turbo --save-dev

您也可以選擇性地全域安裝 turbo,以便在使用 Turborepo 時更加方便。

終端機
npm install turbo --global

步驟 8:新增 turbo.json

在根目錄建立 turbo.json 以註冊您的任務並描述其任務依賴項。

./turbo.json
{
  "tasks": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": [".next/**", "!.next/cache/**"]
    },
    "dev": {
      "cache": false,
      "persistent": true
    }
  }
}

步驟 9:執行 turbo build

使用 Turborepo 建置應用程式。使用全域 turbo,這將是 turbo build。您也可以透過套件管理器執行命令

終端機
npx turbo run build

步驟 10:啟用遠端快取(可選)

預設情況下,當您執行時,Turborepo 將連線到免費使用的 Vercel 遠端快取

終端機
turbo login
turbo link

您也可以設定自行託管的遠端快取,這不需要授權或任何其他費用。

進階遷移考量

雖然上面的遷移指南是一個很好的起點,但 monorepo 的可能性和功能範圍意味著很難為所有情況建立通用化的說明。下面,我們列出了一些您可能正在考慮的常見後續步驟。

逐步遷移複雜的 monorepo

我們鼓勵逐步遷移,這表示您的儲存庫中將同時擁有 Nx 和 Turborepo。請務必花時間了解 Nx 任務圖的建構方式。分割任務圖可能包括以下策略:

  • 一次遷移一個任務:將 nx run lint 變更為 turbo run lint
  • 一次遷移一個套件/專案:將 nx run-many lint test --projects=web 變更為 turbo run lint test --filter=web
  • 雙重執行您的某些任務:為了確保穩定性,您可能會選擇在遷移的早期階段仍然感到舒適並建立確定性時,同時執行 turbo run lintnx run lint

在使用的位置安裝依賴項

Turborepo 建議在使用的位置安裝套件,以提高快取命中率、協助依賴項修剪功能,並向開發人員闡明哪些依賴項適用於哪些套件。這與 Nx 策略不同,在 Nx 策略中,所有依賴項都安裝在儲存庫的根目錄中,使工作區中所有套件都可以使用所有依賴項。

從歷史上看,Nx 一直建議在儲存庫的根目錄中安裝所有依賴項,使工作區中所有套件都可以使用所有依賴項。如果您遵循此指南,我們強烈建議您將依賴項移動到需要它們的套件和應用程式的 package.json 中。請造訪我們關於管理依賴項的文件以了解更多資訊。

建立共用套件

您將大致按照與上述相同的步驟,將套件新增至套件管理器的工作區。

  1. 確保套件的目錄包含在工作區定義中(例如 ./packages/*)。
  2. 將 package.json 新增至套件,其中包含套件需要執行的指令碼。
  3. 檢查 turbo.json 中的任務依賴項,以確保您的依賴項圖符合您的需求。

多語言 monorepo

Turborepo 原生支援 JavaScript 和 TypeScript,並輔助支援您想要使用的任何其他語言。請造訪多語言支援文件以了解更多資訊。

設定對應

nx.json 中找到的設定可以使用下表對應到 turbo.json

用於捕獲檔案的大部分 glob 在 Nx 和 Turborepo 之間是相同的。請參閱我們的檔案 glob 規格以了解詳細資訊和邊緣案例。

全域設定

NxTurborepo
sharedGlobalsglobalDependencies
sharedGlobals.envglobalEnv
sharedGlobals.namedInputglobalDependencies
cacheDirectorycacheDir

任務設定

NxTurborepo
inputs 檔案tasks[task].inputs
inputs.envtasks[task].env
outputs 檔案tasks[task].outputs
cachetasks[task].cache

CLI 對應

NxTurborepo
nx generateturbo generate
nx runturbo run
nx run-manyturbo run
nx reset--force
--parallel--concurrency
--nxBail--continue
--projects--filter
--graph--graph
--output-style--log-order
--no-cloud--cache
--verbose--verbosity