14 KiB
DramaLing 前端系統架構分析報告
📋 專案概覽
技術棧:
- 框架:Next.js 15.5.3 (App Router)
- 語言:TypeScript 5.9.2
- 狀態管理:Zustand 5.0.8
- 樣式:Tailwind CSS 3.4.17
- 圖標:Lucide React
- 部署:Zeabur
專案規模:
- 約 150+ 個組件和模組文件
- 8 個主要路由頁面
- 5 個 Zustand Store
- 多層級的服務和工具函數架構
🏗️ 系統架構層次
1. 目錄結構分析
frontend/
├── app/ # Next.js App Router 頁面
│ ├── flashcards/ # 詞卡管理頁面
│ ├── generate/ # AI 生成頁面
│ ├── review/ # 複習系統頁面
│ ├── review-design/ # 複習設計頁面
│ └── settings/ # 設定頁面
├── components/ # React 組件庫
│ ├── shared/ # 共享基礎組件 (12個)
│ ├── flashcards/ # 詞卡功能組件 (10個)
│ ├── review/ # 複習系統組件 (20+個)
│ ├── generate/ # AI生成組件 (5個)
│ ├── ui/ # 基礎UI組件 (1個)
│ ├── word/ # 詞彙分析組件 (3個)
│ └── media/ # 媒體組件 (已重構)
├── hooks/ # 自定義 Hook 層
│ ├── flashcards/ # 詞卡邏輯 (7個)
│ ├── review/ # 複習邏輯 (2個)
│ ├── generate/ # 生成邏輯 (2個)
│ └── shared/ # 共享邏輯 (1個)
├── store/ # Zustand 狀態管理
│ ├── useReviewSessionStore.ts # 複習會話
│ ├── useTestQueueStore.ts # 測試佇列
│ ├── useReviewDataStore.ts # 複習數據
│ ├── useTestResultStore.ts # 測試結果
│ └── useUIStore.ts # UI狀態
├── lib/ # 核心服務層
│ ├── services/ # API 服務
│ ├── utils/ # 工具函數
│ ├── types/ # 類型定義
│ └── config/ # 配置管理
└── types/ # 全域類型定義
🎯 架構設計模式分析
2.1 分層架構模式 (Layered Architecture)
┌─────────────────┐
│ 表現層 (UI) │ ← React 組件
├─────────────────┤
│ 業務邏輯層 │ ← Custom Hooks
├─────────────────┤
│ 狀態管理層 │ ← Zustand Stores
├─────────────────┤
│ 服務層 (API) │ ← API Services
└─────────────────┘
設計優勢:
- ✅ 職責分離清晰
- ✅ 層次間耦合度低
- ✅ 易於測試和維護
- ✅ 支援並行開發
2.2 Hooks + Store 雙層模式
Hook 層(業務邏輯封裝):
- 包裝 Store 操作 + API 呼叫
- 提供組件友好的介面
- 處理複雜的業務邏輯
Store 層(純狀態管理):
- Zustand 全域狀態
- 跨組件狀態同步
- 最小重渲染優化
📊 組件架構分析
3.1 共享組件庫 (components/shared/)
基礎組件 (12個):
BluePlayButton- 統一播放按鈕 🆕ContentBlock- 內容區塊ErrorState- 錯誤狀態顯示LoadingState- 載入狀態Modal- 彈窗組件Navigation- 導航列PaginationControls- 分頁控制ProtectedRoute- 路由保護StatisticsCard- 統計卡片TabNavigation- 標籤導航Toast- 通知系統ValidatedTextInput- 驗證輸入框
設計評價:⭐⭐⭐⭐⭐
- 組件職責單一,重用性高
- API 設計一致,易於使用
- 支援主題化和客製化
3.2 功能專用組件
詞卡組件 (10個):
- 完整的 CRUD 操作組件
- 圖片生成和管理組件
- 搜尋和篩選組件
複習組件 (20+個):
- 7 種複習模式的測試組件
- 統一的測試結果顯示
- 進度追蹤組件
AI生成組件 (5個):
- 句子分析組件
- 詞彙選擇組件
- 慣用語展示組件
🔄 狀態管理分析
4.1 Zustand Store 設計
架構優勢:
- 使用
subscribeWithSelector中間件優化性能 - Store 按功能域分離,避免巨大單體
- 狀態更新邏輯集中化
Store 職責劃分:
-
useReviewSessionStore - 複習會話核心狀態
- 當前詞卡、進度、模式設定
- 會話生命週期管理
-
useTestQueueStore - 測試佇列邏輯
- 智能優先級算法
- 測試順序管理
-
useReviewDataStore - 複習資料管理
- 待複習詞卡載入
- 數據快取機制
-
useTestResultStore - 測試結果追蹤
- 答題結果記錄
- 統計數據計算
-
useUIStore - UI 狀態管理
- 全域 UI 狀態
- 主題和設定
4.2 Hook 封裝層
設計模式:Store 包裝器 + 業務邏輯
// 範例:useReviewSession Hook
export const useReviewSession = () => {
const store = useReviewSessionStore()
// 業務邏輯:載入下一張卡片
const loadNextCard = async () => {
try {
store.setLoading(true)
const result = await flashcardsService.getDueFlashcards()
store.setDueCards(result.data)
} catch (error) {
store.setError(error.message)
} finally {
store.setLoading(false)
}
}
return { ...store, loadNextCard }
}
🛠️ 服務層架構
5.1 API 服務設計
統一 API 架構:
// lib/services/flashcards.ts
class FlashcardsService {
private baseURL = 'http://localhost:5008'
// 統一的請求處理
private async makeRequest<T>(endpoint: string): Promise<ApiResponse<T>>
// 業務方法
async getFlashcards(): Promise<ApiResponse<Flashcard[]>>
async createFlashcard(data: CreateFlashcardRequest): Promise<ApiResponse<Flashcard>>
}
優勢:
- 統一的錯誤處理機制
- 類型安全的 API 介面
- 支援開發/生產環境切換
5.2 工具函數層
核心工具:
cefrUtils.ts- CEFR 等級處理flashcardUtils.ts- 詞卡工具函數testUtils.ts- 測試相關工具
📈 性能分析
6.1 現況評估
優勢:
- ✅ 使用 Next.js App Router 的最新優化
- ✅ Tailwind CSS 的 purge 機制
- ✅ TypeScript 的編譯時優化
問題識別:
- ❌ 缺乏組件記憶化 (React.memo)
- ❌ 大型組件未進行代碼分割
- ❌ 圖片資源未優化 (WebP, 響應式)
- ❌ 無 Service Worker 快取機制
6.2 Bundle 分析 (推估)
目前 Bundle 大小:
- 主應用:~2.5MB (開發模式)
- 複習模組:~800KB
- AI生成模組:~400KB
- 詞卡模組:~600KB
🔧 具體優化建議
7.1 立即可實施 (本週)
-
組件記憶化:
// 高頻重渲染組件加上 React.memo export const FlashcardCard = React.memo(FlashcardCard) export const VocabularyStatsGrid = React.memo(VocabularyStatsGrid) -
圖片優化:
// 添加圖片懶載入 <img loading="lazy" src={imageUrl} alt="..." /> -
Hook 合併:
// 合併相似的 TTS 播放邏輯 const useTTSManager = () => { // 統一的 TTS 邏輯 }
7.2 短期優化 (2-4週)
-
代碼分割:
// 路由級別的懶載入 const ReviewPage = lazy(() => import('./review/page')) const GeneratePage = lazy(() => import('./generate/page')) -
Store 重構:
// 拆分大型 Store const useTestQueueCore = create(...) // 核心邏輯 const useTestQueueUI = create(...) // UI 狀態 -
API 快取:
// 實施 SWR 或 React Query const { data, error, mutate } = useSWR('/api/flashcards', fetcher)
7.3 中期重構 (1-2月)
-
微前端模組化:
// 按功能拆分獨立模組 apps/ ├── flashcards-module/ ├── review-module/ ├── generate-module/ └── shell-app/ -
設計系統:
// 建立完整的設計系統 components/ ├── atoms/ # 原子組件 ├── molecules/ # 分子組件 ├── organisms/ # 有機體組件 └── templates/ # 頁面模板 -
測試體系:
// 完整的測試覆蓋 __tests__/ ├── components/ # 組件測試 ├── hooks/ # Hook 測試 ├── stores/ # Store 測試 └── e2e/ # E2E 測試
🎯 架構成熟度評分
| 分類 | 評分 | 說明 |
|---|---|---|
| 組件設計 | ⭐⭐⭐⭐⭐ | 模組化程度高,重用性良好 |
| 狀態管理 | ⭐⭐⭐⭐ | 分層清晰但複雜度稍高 |
| 類型安全 | ⭐⭐⭐⭐⭐ | TypeScript 覆蓋率完整 |
| 性能優化 | ⭐⭐⭐ | 基礎優化到位,進階優化待加強 |
| 測試覆蓋 | ⭐⭐ | 缺乏完整的測試體系 |
| 文檔完整 | ⭐⭐⭐ | 基礎文檔存在,詳細文檔不足 |
| 可維護性 | ⭐⭐⭐⭐ | 架構清晰,但複雜度需控制 |
整體評分:⭐⭐⭐⭐ (4/5) - 優秀的現代前端架構
🔍 深度分析:雙層設計模式
Hook + Store 雙層設計詳解
你提到的重點:為什麼要 Hook 和 Store 兩層?
實際案例分析:
Store 層 (純狀態)
// useReviewSessionStore.ts
{
currentCard: ExtendedFlashcard | null,
isLoading: boolean,
setCurrentCard: (card) => set({ currentCard: card }),
setLoading: (loading) => set({ isLoading: loading })
}
Hook 層 (業務邏輯)
// useReviewSession.ts
export const useReviewSession = () => {
const store = useReviewSessionStore()
const loadNextCard = async () => {
store.setLoading(true) // Store 操作
const result = await flashcardsService.getDueFlashcards() // API 呼叫
store.setCurrentCard(result.data[0]) // Store 操作
store.setLoading(false) // Store 操作
}
return { ...store, loadNextCard } // Store + 業務邏輯
}
📊 雙層設計的價值
優點:
- 關注點分離: Store 專注狀態,Hook 專注邏輯
- 重用性: Store 可被多個 Hook 使用
- 可測試性: 可獨立測試狀態邏輯和業務邏輯
- 擴展性: 新功能容易添加新 Hook
缺點:
- 學習成本: 開發者需理解兩層概念
- 複雜度: 簡單功能可能過度工程
- 調試難度: 狀態流向更複雜
🤔 是否過度設計?
分析:
適合雙層的場景:
- ✅ 複習系統:複雜狀態 + 複雜邏輯
- ✅ 詞卡管理:多種操作模式
- ✅ AI 生成:異步處理 + 狀態追蹤
可能過度的場景:
- ❓ 簡單的 UI 狀態管理
- ❓ 一次性業務邏輯
- ❓ 純工具函數封裝
🚨 發現的架構問題
問題 1: Hook 邏輯重複
現象:多個組件都有相似的 TTS 播放邏輯
影響:代碼重複,維護成本高
解決:✅ 已通過 BluePlayButton 組件統一
問題 2: Store 複雜度過高
現象:useTestQueueStore 有 394 行代碼
影響:難以理解和維護
建議:拆分為多個小 Store
問題 3: 類型定義分散
現象:類型定義在多個地方重複 影響:類型不一致,重構困難 建議:建立統一的類型註冊中心
問題 4: 缺乏性能優化
現象:沒有 React.memo, lazy loading 影響:不必要的重渲染 建議:實施組件記憶化策略
🎯 優化路線圖
Phase 1: 立即優化 (1週)
- 組件記憶化 (React.memo)
- 圖片懶載入
- 統一 TTS 邏輯 ✅
Phase 2: 短期優化 (2-4週)
- Store 拆分重構
- 代碼分割實施
- API 快取機制
Phase 3: 中期重構 (1-2月)
- 設計系統建立
- 測試框架完整化
- 性能監控整合
Phase 4: 長期規劃 (2-3月)
- 微前端架構
- PWA 功能
- 國際化支援
💡 關鍵建議
建議 1: 簡化狀態管理
當前:Hook + Store 雙層 建議:評估是否需要簡化為單層(對於簡單狀態)
建議 2: 實施性能優化
優先級:🔴 高
- 添加 React.memo 到高頻組件
- 實施路由級代碼分割
- 圖片和資源優化
建議 3: 建立測試體系
優先級:🟡 中
- 單元測試 (Jest + RTL)
- 整合測試
- E2E 測試 (Playwright)
建議 4: 文檔完善
優先級:🟡 中
- Storybook 組件文檔
- API 文檔
- 架構決策記錄 (ADR)
📋 總結
DramaLing 前端架構整體優秀,採用現代的分層設計模式,組件化程度高,類型安全性強。
核心優勢:
- 清晰的模組分離
- 良好的開發體驗
- 強大的功能完整性
改進空間:
- 性能優化需要加強
- 複雜度控制需要平衡
- 測試和文檔需要完善
推薦策略: 採用漸進式重構,優先解決性能問題,然後逐步優化架構複雜度,建立完整的測試和文檔體系。
報告生成時間: 2025-10-01 分析範圍: Frontend 系統完整架構 建議更新頻率: 每月一次