前端架構師 是做什麼的?
設計最簡潔的結構,讓它在程式庫擴大五倍時依然合理。 偏好無趣、廣為人知的模式。每次添加的抽象層都必須消除比它引入的更多複雜性。
1. 先理解,再建構
- 閱讀現有應用:框架與路由器、渲染模式(SPA、SSR、RSC、靜態)、資料來源、目前的狀態函式庫、樣式方法、測試、建置工具。
- 找出核心使用者流程以及每個流程所需的資料。架構必須追隨資料。
- 注意限制條件:團隊規模、SEO 需求、離線需求、即時需求、效能預算。
2. 元件:各司其職
遵循 React 官方文件所謂的「Thinking in React」方法:
- 將 UI 拆解成層級結構;每個元件只做一件事。如果一個元件需要長篇描述,就將它拆分。
- 先以資料建立一個靜態版本。
- 找出最小的狀態。任何可以從 props 或其他狀態衍生的值都應該被計算,而非儲存。
- 將每個狀態片段放在使用它的元件中最接近的共同擁有者中。
- 向下傳遞回呼;資料單向流動。
元件的層級:
- 基本元件(Primitives):Button、Input、Select、Dialog、Tooltip。具備無障礙性、以令牌設定樣式,不含任何商業邏輯。偏好使用無頭函式庫(Radix、React Aria、Headless UI、Ark),而非自行實作焦點管理。
- 模式(Patterns):FormField、DataTable、EmptyState、PageHeader。組合基本元件。
- 功能(Features):InvoiceList、BillingSettings。負責單一領域的資料擷取與商業規則。
- 路由/頁面(Routes/pages):組合功能;處理參數、佈局與載入邊界。
組合勝於配置:偏好使用 children/插槽,而非帶有二十個布林屬性的元件。
3. 狀態:先分類
| 類型 | 存放位置 |
|---|---|
| 伺服器狀態(來自 API 的資料) | 快取函式庫:TanStack Query、SWR、RTK Query,或框架的載入器/伺服器元件。永遠不要複製到全域儲存中。 |
| URL 狀態(篩選器、分頁標籤、分頁、選取項目) | URL(搜尋參數、路由參數)。 |
| 表單狀態 | 表單函式庫(React Hook Form、Conform、原生表單 + 動作)或非受控輸入元件。 |
| 本地 UI 狀態(開/關、懸停) | 元件狀態。 |
| 共享客戶端狀態(工作階段、偏好設定、多步驟草稿) | 低頻率值使用 Context;只有在許多遠端元件經常更新時才使用 Zustand/Jotai/Redux。 |
對於低風險的變更使用樂觀更新,並在發生錯誤時回滾。對於任何雙擊可能重複的操作,使用具冪等性的變更。
4. 資料夾結構
按功能組織,搭配一個少量的共享層:
src/
app/ 或 routes/ # 路由、佈局、載入/錯誤邊界
features/
billing/
components/
api.ts # 此領域的查詢與變更
hooks.ts
types.ts
index.ts # 功能的公開表面
components/ui/ # 基本元件與模式(設計系統)
lib/ # 與框架無關的輔助工具、API 客戶端
styles/ # tokens.css、全域重置
規則:功能從 components/ui 和 lib 匯入,永遠不從另一個功能的內部匯入(需透過其 index.ts)。不要有 utils.ts 垃圾桶;根據輔助工具的用途來命名。
5. 樣式策略
- 以 CSS 自訂屬性作為令牌的單一事實來源(請參閱
frontend-design技能的tokens.md或design-system-generator技能)。 - 為程式庫選擇一種樣式方法:對應到令牌的 Tailwind、CSS Modules,或是零執行時的 CSS-in-JS / 原子系統(vanilla-extract、StyleX、Panda)。在效能敏感或伺服器渲染的應用程式中避免執行時 CSS-in-JS。
- 保持 Specificity 扁平;變體應透過 props 實現,而非層疊覆蓋。
6. 效能與品質預算
- 設定預算:在中階手機上 LCP < 2.5 秒、INP < 200 毫秒、CLS < 0.1;每條路由的 JS 預算。
- 按路由進行程式碼分割;懶加載大量、位於摺疊線下方或僅供互動的元件。
- 為非同步內容保留空間;虛擬化長列表;將繁重工作移至主執行緒之外。
- 圖片:使用現代格式、明確尺寸、響應式
srcset,僅為 LCP 圖片設定優先權。 - 字型:自行託管、子集化、節制地預先載入、
font-display: swap。 - 無障礙性即是架構:基本元件負責焦點管理與 ARIA,因此功能不會出錯。加入自動化檢查(測試中的 axe、eslint-plugin-jsx-a11y)到 CI。
- 每個路由和每個獨立小工具設定錯誤邊界;一次失敗絕不癱瘓整個應用。
7. 產出
交付:簡短的架構摘要(技術棧、渲染模式、狀態分類)、資料夾樹狀圖、主要流程的元件層級、資料擷取方式,以及若重整現有應用則提供可逐步交付的遷移計畫。說明取捨以及你刻意未添加的內容。
檢查清單
- 每個狀態片段都有一個擁有者與一種類型(伺服器、URL、表單、本地、共享)。
- 伺服器資料已快取,未複製到全域儲存中。
- 功能透過公開的 index 隔離;基本元件不含商業邏輯。
- 一種樣式方法,由令牌驅動。
- 存在路由層級的程式碼分割與載入/錯誤邊界。
- 已定義效能預算與無障礙性檢查,並在可能的情況下自動化。