Published on

將公司專案轉換成 Monorepo 遇到的那些事 - 第三篇 介紹 Nx Library Type

Authors
  • avatar
    Name
    Alex Yu
    Twitter

第三篇 介紹 Nx Library Type

在使用 Nx 進行開發時,最重要的概念之一就是如何有效地管理和組織程式碼,這通常是通過切分不同類型的 Library 來達成的。在這篇文章中,我們將深入探討為什麼需要將程式碼切分為不同的 Library 類型,它們的好處與壞處,以及 Nx 為什麼選擇這樣的切分方式。

為什麼要規劃函式庫

清晰的程式碼結構

將程式碼劃分為不同的函式庫可以使整體架構更加清晰。每個函式庫專注於特定的功能或領域,這樣開發人員能夠更容易地理解和維護程式碼。例如,功能函式庫可以專注於業務邏輯,而 UI 函式庫則專注於呈現層。這種模組化的設計使得團隊可以獨立開發和測試各個部分。這不僅提高了程式碼的可讀性,也讓新成員更容易上手。

促進程式碼重用

通過將常用功能或組件抽象為函式庫,可以在多個應用程式或服務中重用這些程式碼,從而減少重複開發的工作量。例如,如果多個應用程式都需要使用相同的驗證邏輯,可以將其放入一個工具函式庫中,所有應用程式都可以引用該函式庫。這不僅節省了時間,還降低了出錯的可能性。

提高團隊協作

當程式碼被組織成函式庫時,不同團隊可以同時在不同的函式庫上工作,而不會互相干擾。這樣可以提高開發效率,特別是在大型專案中。團隊成員可以專注於自己的領域,並在需要時進行整合。此外,這種分工還能促進知識共享,因為每個團隊都能夠對其負責的函式庫進行深入了解。

符合業務需求變化

隨著業務需求的不斷變化,將程式碼劃分為不同的函式庫使得調整和擴展變得更加靈活。例如,如果某個功能需求增加,可以輕鬆添加新的功能函式庫或擴展現有函式庫,而不會影響到整體架構。這種靈活性對於快速迭代和響應市場變化至關重要。

帶來的好處

  1. 可維護性:

    • 模組化的程式碼結構使得每個函式庫都能獨立維護和更新,降低了對其他部分的影響。當某個功能需要改進或修復時,只需更新相關函式庫,而不必擔心影響整體系統。
  2. 版本控制一致性:

    • 所有相關的函式庫都在同一個版本控制系統中,這樣可以確保版本的一致性,減少因版本不匹配而導致的問題。當一個函式庫更新時,可以輕鬆地通知依賴該函式庫的其他部分進行相應更新。
  3. 簡化測試流程:

    • nx test my-feature-lib
  4. 增強可擴展性:

    • 隨著需求變化,可以輕鬆添加新的功能函式庫或擴展現有函式庫,而不會影響到整體架構。例如,如果某個功能需求增加,可以將其從現有功能函式庫中提取出來,形成一個新的子函式庫。
  5. 提升性能:

    • 通過將程式碼劃分為小型、專注的函式庫,可以更容易地識別性能瓶頸並進行優化。這種結構使得性能調優針對性更強,有助於提升整體應用程式的響應速度和穩定性。
  6. 促進知識共享與標準化:

    • 當多個團隊使用相同的函式庫時,可以促進知識共享和最佳實踐的標準化。這有助於提高整體開發質量,使新成員能夠快速適應團隊工作流程。

可能的壞處

  1. 初期設計成本:
    • 在專案初期,需要花費時間和精力來設計和實現這種模組化結構。如果專案的需求不明確,可能會導致過度設計。在這種情況下,開發者可能會建議先從簡單的結構開始,再根據需求逐步擴展。
  2. 依賴管理複雜性:
    • 隨著函式庫數量的增加,管理它們之間的依賴關係可能變得複雜。需要仔細考慮依賴圖,以避免循環依賴等問題。Nx 提供了工具來幫助可視化依賴關係,但仍需謹慎管理。
  3. 學習曲線:
    • 對於不熟悉 Nx 或 monorepo 概念的新成員來說,理解如何使用和管理這些函式庫可能需要一定的學習時間。團隊應考慮提供培訓或文檔,以幫助新成員快速上手。
  4. 過度拆分:
    • 如果拆分過度,會導致過多的小 Library,使得管理變得更加複雜,甚至反而影響開發效率。
  5. 版本衝突:
    • 在多個團隊同時開發時,不同團隊可能會對同一函式庫進行不同版本的修改。如果沒有良好的溝通和版本控制策略,可能會導致衝突和混亂。因此,在實施前需要制定明確的版本管理規範。

Nx Library 的類型

Application Library

  • 用途:通常包含應用程式的核心邏輯或功能,這些邏輯不會在其他應用中重複使用,但對於該應用至關重要。
  • 範例:一個專門處理用戶登錄的邏輯,可能只會在特定應用中使用。
  • 依賴關係:只能依賴於 Feature Library、UI Library、Data Access Library、Utility Library。
  • 禁止的操作:應避免被其他應用程式或 Library 引用,因為其邏輯通常是專屬於某應用的。

Feature Library

  • 用途:用於封裝應用中的某個具體功能,這些功能模塊是獨立的,能夠在多個應用中被重用。
  • 範例:例如,電子商務應用中的“購物車”功能,這可以在多個應用中使用。
  • 依賴關係:可以依賴於 Data Access Library、UI Library 和 Utility Library。
  • 禁止的操作:不能直接依賴 Application Library,因為這可能會導致不必要的耦合。

UI Library

  • 用途:封裝和共享 UI 元件,這些元件通常是通用的 UI 組件或視覺組件,可以在多個應用中重用。
  • 範例:常見的 UI 元件如按鈕、表單、卡片元件等。
  • 依賴關係:可以依賴於 Utility Library,但不應依賴 Feature Library 或 Data Access Library。
  • 禁止的操作:避免混入業務邏輯,確保 UI Library 僅專注於視覺呈現。

Data Access Library

  • 用途:管理資料存取邏輯,將 API 請求、數據格式化等邏輯封裝在一個可重用的模塊中,讓應用程式能夠共享這些邏輯。
  • 範例:處理與後端 API 的溝通,或者處理數據庫查詢邏輯的庫。
  • 依賴關係:可以依賴於 Utility Library,但不能依賴 UI Library 或 Feature Library,避免與視覺層耦合。
  • 禁止的操作:應避免引入過多的應用邏輯。

Utility Library

  • 用途:封裝通用的工具函數或服務,這些工具函數可以在應用程式的各個部分中被使用。
  • 範例:日期處理、字串操作、數學運算等函數庫。
  • 依賴關係:應保持獨立,不依賴其他 Library,從而保證最小化的耦合。
  • 最佳實踐:設計成完全無依賴的模塊,使其在任何地方都能直接被引用。
Nx libray Type

為什麼 Nx 要這樣切分 Library?

Nx 的 Library 類型切分基於功能而非框架或技術架構。這種切分方式的好處在於:

  • 更高的可重用性:Nx 的 Library 類型基於功能模塊的劃分,而不是技術架構。這使得每個 Library 可以在不同的應用中被重用,而不需要依賴於特定的框架或技術。
  • 清晰的程式碼結構:這種劃分方式使得程式碼結構更加清晰,開發者可以更容易理解每個 Library 的職責,從而提高維護性。
  • 促進分層架構:通過將功能拆分為不同的 Library,開發者可以更容易地實現分層架構(如 Vertical Slice Architecture),將每個功能模塊都封裝在獨立的 Library 中,從而提高程式碼的可測試性、可擴展性和可維護性。
  • 支持跨應用開發:這種方式支持跨應用開發,因為每個 Library 都是獨立且可重用的,開發者不需要重複構建相同的功能。

使用 Nx 管理函式庫

創建函式庫

使用 Nx CLI 可以輕鬆創建新的函式庫。例如,要創建一個新的功能函式庫,可以使用以下命令:

nx generate @nx/react:library my-feature-lib

這將在 libs/ 目錄下生成一個新的功能函式庫,其中包含必要的文件結構和配置。

管理依賴

Nx 提供了強大的依賴管理工具,可以幫助開發者清晰地了解各個函式庫之間的依賴關係。使用 nx graph 命令,可以生成一個視覺化圖表,顯示項目之間的相依性,這對於大型項目尤為重要。

測試和構建

每個庫都可以獨立進行測試和構建。Nx 支援 Jest 和 Cypress 等測試框架,使得編寫單元測試和端到端測試變得簡單。例如,要運行某個函式庫的測試,可以使用以下命令:

nx test my-feature-lib

如何擴充函式庫關係

利用 Nx 的 Project Graph

Nx 提供了 Project Graph 功能,可以幫助開發者視覺化不同函式庫之間的依賴關係。通過 nx graph 命令,可以生成一個圖表,顯示所有應用程式和函式庫之間的相依性。這對於理解整體架構及其變更影響至關重要。

實施步驟:
  • 運行 nx graph 命令以生成當前專案的依賴圖。
  • 分析生成圖表以確定哪些部分之間存在依賴關係。
  • 根據依賴關係調整專案結構,以避免循環依賴問題。
動態擴展

當需求變化時,可以根據實際情況動態擴展現有的函式庫。例如,如果某個功能需要進一步拆分,可以將其從功能函式庫中提取出來,形成一個新的子函式庫。這樣做不僅保持了程式碼的整潔性,也能夠簡化未來的維護工作。

實施步驟:
  • 確定需要拆分或合併的功能區域。
  • nx generate @nx/react:library new-feature-lib
  • 更新相關依賴,以反映新的結構。
標準化接口

在設計函式庫時,可以考慮使用標準化接口來促進不同函式庫之間的互操作性。這樣可以確保即使在擴展過程中,各個部分仍然能夠順利協作。例如,定義統一的 API 接口,使得不同功能函式庫之間可以輕鬆調用彼此的方法。此外,在接口設計上保持一致性,有助於減少學習成本並提高開發效率。

實施步驟:
  • 定義公共接口並將其放置在共享位置,例如 libs/shared/interfaces
  • 確保所有相關函數庫遵循該接口。
  • 定期審查接口定義,以適應業務需求變化。
文檔與溝通

隨著專案的擴展,良好的文檔和溝通變得尤為重要。每當新增或修改一個圖表時,都應該更新相關文檔,以便其他團隊能夠了解變更內容。同時,在團隊內部舉辦定期會議,以討論各自負責的圖表及其進展,也是保持良好協作的重要方式。

實施步驟:
  • 使用工具如 Storybook 為 UI 組件創建文檔。
  • 定期更新 README 文件以反映最新狀態。
  • 設置內部 Wiki 或文檔平台以集中存儲信息。

其他切分方式

雖然 Nx 提倡按功能模塊切分 Library,但這並不是唯一的切分方式。還有其他常見的切分方式:

  • 按層次切分:根據應用的層次進行切分,例如將資料存取層、業務邏輯層和展示層分開。這種方式有助於將不同的職責區分開來,但可能會導致過度拆分,增加依賴管理的複雜度。
  • 按技術架構切分:根據所使用的框架或技術架構切分,如將 Angular、React 和 Node 相關的程式碼拆分為不同的 Library。這種方式適用於技術架構差異較大的項目,但可能會導致重複的程式碼,並限制程式碼的重用性。

結論

利用 Nx 的 圖表,不僅能夠提高程式碼的可重用性和維護性,還能增強團隊協作效率。在 monorepo 架構中,有效地管理不同類型的圖表是成功開發大型應用程式的重要關鍵。透過合理地劃分功能圖表、UI 圖表和工具圖表等,我們可以更好地組織程式碼,提高整體開發效率。同時,也需留意潛在挑戰,以便在實施過程中做出適當調整。在未來,我們期待看到更多企業採用 Nx 及其優勢來推動技術創新與業務增長!希望這篇文章能幫助您更深入理解 Nx 圖表 的使用及其優勢!