深入解析 Yarn Workspaces:高效管理 monorepo 的必備技能
本文適用於
Yarn 1.x的版本
關於 Yarn Workspaces
Yarn Workspaces 是 Yarn 提供的一個功能,專門用來管理一個 monorepo 中的多個子專案(通常稱為 workspace)。這些 workspace 可以互相依賴,並且共享相同的依賴,從而提升專案的開發效率,減少重複安裝依賴的開銷。
單一 Workspace 的定義與特性
每個 workspace 本質上是一個包含自己 package.json 文件的獨立 npm 專案,可以相互依賴,也可以作為獨立 npm 套件發佈到 npm 等套件管理平台。
- 獨立運作:每個 workspace 都像是一個獨立的 package,具有自己的 package.json 文件,包含自己專屬的依賴和設定。這允許子專案像是普通的 npm package 一樣被單獨發佈。
- 相互依賴:子專案可以相互依賴,不需重複下載依賴。
Yarn Workspaces 的定義與特性
Yarn Workspaces 允許在一個 monorepo 中同時管理多個子專案,它帶來的好處包括以下幾點:
- 多專案共享依賴:不同子專案可以共用相同的
node_modules目錄,這避免了重複安裝同一個依賴,從而節省磁碟空間和時間。 - 集中化管理:所有子專案的依賴可以統一管理在根目錄的
yarn.lock中,避免了每個子專案都獨立管理依賴的混亂局面。 - 跨專案依賴:子專案之間可以相互依賴,Yarn 會自動解決這些依賴關係,無需手動處理。這讓子專案可以輕鬆引用其他子專案,無需將其 發佈到 npm registry。
- 提升安裝效率:Yarn Workspaces 可以自動將通用的依賴 「提升」(hoist) 到 monorepo 根目錄,避免子專案之間重複安裝相同的依賴,顯著加快安裝速度,特別是在大型專案中效果尤為明顯。
注意事項
使用 Yarn Workspaces 進行開發時,必須特別注意依賴的聲明:
- 依賴未聲明的風險:如果某個子專案 packageA 在開發過程中使用了另一個子專案 packageB 的依賴 dependencyB,但忘記在 packageA 的 package.json 中聲明該依賴,可能在開發和測試階段一切運行正常。這是因為 Workspaces 會共享根目錄的 node_modules,所以 dependencyB 仍能被找到。但當 packageA 發佈到 npm 等平台後,因為依賴聲明不完整,使用者將無法正常運行這個套件,因為 dependencyB 不會被自動安裝。
- 無自動檢查:目前 Yarn Workspaces 沒有自動檢測未聲明依賴的機制,因此開發者需要格外注意,確保每個子專案的 package.json 文件中包含了所有必要的依賴聲明。
配置 Yarn Workspaces
在這一章,我們將介紹如何在 monorepo 中正確配置 Yarn Workspaces,並探討一些在配置過程中常見的問題與解決方法。
根目錄配置
首先,在 monorepo 的根目錄下,我們需要定義 Workspaces 的範圍和設定。根目錄的 package.json 應包含以下兩個重要屬性:
-
private:在根目錄的 package.json 中,必須將 private 設為 true,這是因為 monorepo 的根目錄通常不會作為一個單獨的 npm 套件發佈,而只是用來管理 Workspaces 和共享依賴。如果未將 private 設為 true,Yarn 會警告你這個專案是可發佈的。
-
workspaces:這是一個字串數組,用來定義哪些目錄是 Workspaces。Yarn 支持使用 glob patterns 來匹配特定路徑。例如,
"packages/*"會告訴 Yarn Workspaces 所有位於 packages/ 資料夾下的子目錄都是 Workspaces。package.json{
"private": true,
"workspaces": [
"packages/*"
]
}
個別 workspace 配置
在每個子專案(即 Workspace)中,我們需要配置自己的 package.json 文件。以下是配置時需要注意的幾個要點:
- private:在大多數情況下,個別 Workspace 不需要設置
private: true,因為這些子專案可能會單獨發佈為 npm package。 - package name:Yarn Workspaces 依據每個 package.json 中的 name 屬性來識別專案,而不是使用目錄名稱。因此,在下達
yarn workspace <workspace_name> <command>時,必須使用 package.json 中的 name 屬性,而不是該 Workspace 的目錄名稱。 - 依賴聲明:正如在第一章提到的,在 Workspaces 中開發時,務必確認每個子專案的 package.json 文件包含了所有必要的依賴聲明,避免發佈時出現未聲明依賴的問題。