勇哥

勇哥开发之路

I build things on web.

【翻譯】現代前端應用程序架構

翻譯自:Architectures of modern Front-end applications

在開發過程中,業務需求可能各不相同且經常變化,因此創建一個靈活、可擴展和可維護的架構非常重要。同樣關鍵的是,團隊成員和客戶等每個人都要清楚地了解項目。為了避免大量文件、頻繁開會和不斷改進,我們採用了下面的架構方法。本文章將探討流行架構的優勢,並幫助您選擇最佳解決方案來滿足您的獨特需求。

很多人認為下面列出的架構只是 "文件夾結構",這只是一種說法。事實上,如果深入研究,它們有幾個重要方面:

  • 模塊合作:應用程序中不同模塊 / 組件之間的高效通信和互動(使用基於組件的架構、可重複使用的代碼)。
  • 改進項目導航:以易於導航和維護的方式構建項目(清晰的文件夾層次結構、命名約定、關注點分離)。
  • 業務邏輯與用戶界面組件分離:將業務邏輯(數據獲取、狀態管理)與用戶界面組件分離,以提高可維護性和可重用性(例如,使用 Redux、Context API 等服務或存儲)。
  • DRY: Don’t repeat yourself 不要重複
  • DAC: Divide and conquer 分而治之

請看下圖 -- 我們的重點是右下角的區域,這裡是這些原則最有效的結合點:

Ideal result

理想結果(示例)

我們希望藉助架構來實現這些方面。現在,讓我們對每一種架構進行詳細分析,並根據具體情況選擇最適合的架構。

經典架構(無架構)- Classic architecture (without architecture)#

經典架構是許多人已經在使用的一種方法。我們通常專注於基本概念,將項目劃分為 “頁面”、“組件”、“助手” 等。然而,問題在於隨著應用程序的增長,結構開始瓦解,找到正確的組件或其業務邏輯變得更加困難。讓我們舉例說明:

Components overuse

組件過度使用(示例)

在這個例子中,我們有 3 個頁面,顯然沒有被過度使用。但是,它們可能包含下面顯示的所有組件。如果我們觀察一下這些組件,就會發現真正的 "混亂"🤯:每個組件都會主動使用其他組件,從而在它們之間產生依賴關係。這使得它們難以擴展和重用。

下面是另一個使用 Redux 狀態管理器的示例:

Scattered app logic — Redux state manager

分散的應用程序邏輯 - Redux 狀態管理器(示例)

在我們的設置中,每個組件都由指定的 "還原器" 管理,該還原器負責處理其特定的邏輯。然而,有些組件邏輯被錯誤地放在了不正確的還原器中。出現這種情況的原因可能是開發人員沒有注意到現有的文件,或者由於當時需要的邏輯數量有限而沒有考慮創建一個新文件。因此,一些組件的邏輯現在分散在整個項目中,使其不夠清晰,也更難維護。

下圖展示了一個缺失的架構:

Destructive decoupling —diagram

破壞性解耦示意圖(示例)

這種方法(或者更正確地說,缺乏架構)往往會造成難以跟蹤依賴關係的混亂環境,從而導致混亂,難以為項目提供支持。不過,這種方法在一些特殊情況下可能還是有用的,例如:

  • 小型團隊(1-2 名開發人員)
  • MVP 項目
  • 不是長期支助項目
  • 學習項目或模板

模塊化結構 - Modular architecture#

模塊化架構是一種將應用程序劃分為若干層( pages 、 modules 、 components 、 UI 等)的方法,在這些層中,已經有獨立的模塊,它們有自己的邏輯和責任範圍。

Modular architecture — layer structure

模塊化架構 -- 層結構(示例)

在這個例子中,可以看到應用層的排列方向是一致的: pages → modules → components → ui (如果從另一側看,則相反)。這意味著層數越高(例如 pages ),可以使用的下層層數就越少 -- 組件不能使用模塊,但可以使用用戶界面層的所有內容,而模塊可以使用組件,但不能使用頁面。而頁面已經只能使用模塊了。

Modular architecture — modul & public API

模塊化架構 -- 模塊和公共應用程序接口(示例)

如前所述,每個模塊都有自己的職責範圍。同樣重要的是,每個模塊都應該有自己的公共 API( index.ts 文件),它封裝了模塊的所有內部邏輯,只提供外部需要的部分。(這與 OOP 原理非常相似:當一個類有很多私有方法時,這些方法不能從外部訪問,但可以在類本身內部使用)說到 pages 文件,其實很簡單:理想情況下,它應該只是模塊和組件的封裝,應用程序的所有業務邏輯都應該放在模塊和組件的層面上。

(⚠️) 重要:一個模塊不應使用另一個模塊,一個組件不應包含複雜的邏輯。如果仍然需要邏輯,則應盡可能簡單和易於維護,否則 -- 它就是一個模塊!

請看下圖:

Almost Ideal— diagram

近似理想圖(示例)

但是我們仍然有 components/ 和 ui/ 這樣的全局目錄,它們可能會被過度使用。在某些情況下,邏輯可能會增長,不再總是很清楚什麼是組件,什麼是模塊。此外,我們還經常發現,隨著應用程序的增長,開發人員開始在其他模塊中使用模塊,這就破壞了該架構的原則,並造成不必要的依賴。儘管如此,我們的架構提供了以下功能:

  • 單線程
  • 在不同層級重複使用組件的能力
  • 近乎完美的層次感
  • 封裝

功能分片設計(FSD)架構 - Feature Sliced Design#

FSD-Overview

概述 - https://feature-sliced.design/

功能切片設計(FSD)架構 -- 與模塊化架構有很多相似之處,但也避免了我們上面討論過的情況。這種方法是按功能區域(特性)而不是按層來構建項目。這種組織方式有助於避免全局目錄增長(如模塊化架構中的 components 、 UI ),並在組件、模塊和層之間提供了明確的職責分工。

FSD — layers example

FSD - 圖層示例

架構的構建方式是,頂層 pages 整合並組織所有子模塊和組件的工作,而每一層則提供更詳細、更具體的功能和元素。是的,我們在這裡遵循同樣的規則 -- 層級越高(例如 pages ),可以使用的下層層級就越少:

  • 頁面 - 頂層包含應用程序中顯示的 pages 。
  • 進程 - 在此架構中已被棄用,因此我們可以跳過它。
  • 功能 / 小工具 - pages 下面是主要的 features 塊,這些塊構建了頁面的核心功能,使其具有可管理性和獨立性。
  • 實體(Entities)-- 功能模塊下面的 entities 是由 "共享" 層中可用的較簡單用戶界面組件編譯而成的。
  • 共享 - 底層包含通用的用戶界面組件,可用於應用程序的不同部分。

(⚠️) 重要:與模塊化架構一樣,各層之間不要過度使用。

Overview (slices segments)

概述(片 / 段)- https://feature-sliced.design/

FSD 体系結構以模塊化元素為特色,稱為 "片" 和 "段"。"切片" 指的是每一層中的模塊,每個模塊代表一個不同的業務實體。同時,"段" 包含各種結構組件,如 api/components/config/ constants/ 等,將架構組織成更清晰、更易於管理的部分。

最後,我們達到了目標結果:

Ideal — diagram (example)

理想 - 圖表(示例)

將這種方法集成到項目中既不容易也不快速。它至少需要最低限度的架構知識,而且你必須牢記這可能需要時間。但是,掌握 FSD 的使用方法可以:

  • 結構清晰
  • 層次分明
  • 靈活組件
  • 獨立模塊
  • 平衡重用性

順便說一句,這種架構提倡在文件命名中使用 "kebab case"👀。

product-description.vue / shopping-cart.tsx / get-base-url.ts / 等等。

使用 "模塊化架構" 的實例:

使用 "FSD 架構" 的實例:

結論#

在本文中,我們探討了經典架構、模塊化架構和 FSD 架構之間的區別,並討論了它們的用途。

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。