Rush Stack商店部落格活動
跳至主要內容

Rush 子空間

什麼是子空間?

子空間是 Rush 的一項功能,可讓單一單體儲存庫使用多個 PNPM 鎖定檔進行安裝。例如,如果子空間名稱為 my-team,則會有一個資料夾 common/config/subspaces/my-team/,其中包含 pnpm-lock.yaml 檔案和相關設定。每個 Rush 專案都只屬於一個子空間,而單體儲存庫仍然只有一個統一的「工作區」。因此,專案的 package.json 檔案可以使用 workspace: 指定詞來相依於其他子空間的專案。

有什麼好處?

一般來說,最好為整個單體儲存庫使用單一鎖定檔,因為這樣可以最佳化安裝時間,並盡量減少管理版本衝突的維護工作。但是,在某些情況下,使用多個鎖定檔具有優勢。

  • 非常大的程式碼庫:鎖定檔可以視為一個巨大的多變數方程式,我們透過協調許多專案中的 NPM 套件版本選擇來解決這個方程式,以消除衝突並盡量減少重複。(Lockfile Explorer 文件深入說明了這一點。)將單體儲存庫相依性分成較小的鎖定檔確實會使這些方程式變小且更容易解決,但代價是增加了管理版本的總開銷。對於非常大的工程團隊來說,分配工作可能比盡量減少總工作量更重要。

  • 分離的專案集:大型程式碼庫可能會有某些專案叢集,其相依性與儲存庫的其餘部分不一致。例如,假設有 50 個專案組成一個使用已淘汰或過時框架的舊版應用程式,而沒有進行現代化的商業動機。將這些專案移至子空間可讓其版本控制獨立管理。

  • 安裝測試:發佈 NPM 套件時,某些錯誤無法使用 workspace:* 符號連結來重現。例如,虛擬相依性或不正確的 .npmignore 全域模式會導致套件的外部使用者發生失敗,但在單體儲存庫中測試相同的程式庫時,可能會運作良好。將測試專案移至子空間(與注入的相依性結合使用)會產生更精確的安裝,可以發現此類問題,同時仍然避免實際發佈到測試 NPM 登錄的開銷。

我需要多少子空間?

我們通常建議「盡可能少」,以盡量減少額外的版本管理開銷。每個團隊一個子空間是一個合理的上限。也就是說,此功能已在具有 1,000 多個子空間的生產單體儲存庫中成功使用。

真實世界示範

Rush Stack 在 GitHub 上的自有儲存庫目前設定了兩個子空間

功能設計

每個子空間都必須在 common/config/subspaces.json 設定檔中集中註冊其名稱。專案使用 rush.json 中的 subspaceName 欄位新增至子空間。

每個子空間的設定都放在資料夾 common/config/subspaces/<子空間名稱>/ 中,其中可能包含下列檔案

檔案用途
common-versions.jsonRush 版本覆寫
pnpm-config.jsonPNPM 版本覆寫
pnpm-lock.yamlPNPM 鎖定檔
repo-state.jsonRush 產生以防止手動鎖定檔變更的設定檔
.npmrc套件管理員設定
.pnpmfile-subspace.cjs程式碼版本覆寫,遵循與 .pnpmfile.cjs 相同的規格,但特定於子空間

除了子空間層級之外,某些檔案可以全域設定(適用於整個單體儲存庫)

子空間設定檔全域設定檔繼承
common-versions.json啟用子空間後,禁止使用全域檔案
pnpm-config.jsoncommon/config/rush/pnpm-config.json(仍在開發中)子空間優先,但會忽略某些欄位
pnpm-lock.yaml啟用子空間後,禁止使用全域檔案
repo-state.json啟用子空間後,禁止使用全域檔案
.npmrccommon/config/rush/.npmrc子空間覆寫優先
.pnpmfile-subspace.cjscommon/config/rush/.pnpmfile.cjs子空間覆寫優先

請注意,下列設定檔不會移動

  • common/config/.npmrc-publish:此檔案用於 Rush NPM 發佈,無論發佈的專案屬於哪個子空間
  • common/config/.pnpmfile.cjs:此檔案可以套用將會影響單體儲存庫中所有子空間的版本控制覆寫。為了避免跨鎖定檔的混淆互動,在大多數情況下,最好改用 .pnpmfile-subspace.cjs

如果沒有子空間,Rush 會在 common/temp/ 資料夾中產生並安裝 PNPM 工作區。啟用子空間後,這會在 common/temp/<子空間名稱>/ 等資料夾中單獨執行。

有兩種基本操作模式

  1. 只有少數子空間: 您可以在 subspaces.json 中設定 "preventSelectingAllSubspaces": false,並且 rush install 預設會安裝所有子空間。

  2. 大量的子空間: 如果安裝所有子空間會消耗太多時間和磁碟空間,則您可以設定 "preventSelectingAllSubspaces": true。在此模式下,當叫用 rush installrush update 等指令時,使用者必須以某種方式篩選子空間,例如

    • rush install --to my-project 以僅安裝指定專案的相依性
    • rush install --subspace my-subspace 以僅安裝特定子空間
    • rush install --to subspace:my-subspace 使用專案選取器來為屬於指定子空間的專案安裝

如何啟用子空間

  1. 請確保您的 rush.json 指定 "rushVersion": "5.122.0" 或更新版本,以及 "pnpmVersion": "8.7.6" 或更新版本。

  2. 使用 subspaces.json 來啟用此功能並定義子空間。您可以從 subspaces.json 文件中複製此檔案的範本,或使用 rush init 來產生它。在本教學課程中,我們將建立一個名為 install-test 的子空間,用於測試 NPM 套件

    common/config/rush/subspaces.json

    {
    "$schema": "https://developer.microsoft.com/json-schemas/rush/v5/subspaces.schema.json",

    /**
    * Set this flag to "true" to enable usage of subspaces.
    */
    "subspacesEnabled": false,

    /**
    * When a command such as "rush update" is invoked without the "--subspace" or "--to"
    * parameters, Rush will install all subspaces. In a huge monorepo with numerous subspaces,
    * this would be extremely slow. Set "preventSelectingAllSubspaces" to true to avoid this
    * mistake by always requiring selection parameters for commands such as "rush update".
    */
    "preventSelectingAllSubspaces": false,

    /**
    * The list of subspace names, which should be lowercase alphanumeric words separated by
    * hyphens, for example "my-subspace". The corresponding config files will have paths
    * such as "common/config/subspaces/my-subspace/package-lock.yaml".
    */
    "subspaceNames": [
    // The "default" subspace always exists even if you don't define it,
    // but let's include it for clarity
    "default",

    "install-test" // 👈👈👈 Our secondary subspace name
    ]
    }
  3. 建立 default 子空間資料夾並將現有的設定檔移動到該資料夾

    cd my-repo
    mkdir --parents common/config/subspaces/default

    # Move these files:
    mv common/config/rush/common-versions.json common/config/subspaces/default/
    mv common/config/rush/pnpm-lock.yaml common/config/subspaces/default/
    mv common/config/rush/.npmrc common/config/subspaces/default/

    # Rename this file:
    mv common/config/rush/.pnpmfile.cjs common/config/subspaces/default/.pnpmfile-subspace.cjs
  4. 建立 install-test 子空間資料夾

    cd my-repo
    mkdir --parents common/config/subspaces/install-test
  5. 透過編輯 rush.json 將專案指派給子空間。例如

    rush.json

    . . .

    "projects": [
    {
    "packageName": "my-library-test",
    "projectFolder": "test-projects/my-library-test",
    "subspaceName": "install-test"
    }

    . . .

    如果省略任何專案的 "subspaceName",它們將屬於 default 子空間。

  6. 現在更新新子空間的鎖定檔

    # Clean out the common/temp folder from before
    rush purge

    # Regenerate the "default" subspace:
    rush update --full --subspace default

    # Regenerate the "install-test" subspace:
    rush update --full --subspace install-test

    注意:您可以在不使用 --full 來重新產生任何鎖定檔的情況下移轉到子空間,但這是一個更複雜的過程,可能需要使用指令碼來重寫 pnpm-lock.yaml 檔案中的某些路徑。

另請參閱