dramaling-vocab-learning/DramaLing前端系統架構報告.md

14 KiB
Raw Blame History

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 職責劃分

  1. useReviewSessionStore - 複習會話核心狀態

    • 當前詞卡、進度、模式設定
    • 會話生命週期管理
  2. useTestQueueStore - 測試佇列邏輯

    • 智能優先級算法
    • 測試順序管理
  3. useReviewDataStore - 複習資料管理

    • 待複習詞卡載入
    • 數據快取機制
  4. useTestResultStore - 測試結果追蹤

    • 答題結果記錄
    • 統計數據計算
  5. 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 立即可實施 (本週)

  1. 組件記憶化

    // 高頻重渲染組件加上 React.memo
    export const FlashcardCard = React.memo(FlashcardCard)
    export const VocabularyStatsGrid = React.memo(VocabularyStatsGrid)
    
  2. 圖片優化

    // 添加圖片懶載入
    <img loading="lazy" src={imageUrl} alt="..." />
    
  3. Hook 合併

    // 合併相似的 TTS 播放邏輯
    const useTTSManager = () => {
      // 統一的 TTS 邏輯
    }
    

7.2 短期優化 (2-4週)

  1. 代碼分割

    // 路由級別的懶載入
    const ReviewPage = lazy(() => import('./review/page'))
    const GeneratePage = lazy(() => import('./generate/page'))
    
  2. Store 重構

    // 拆分大型 Store
    const useTestQueueCore = create(...)    // 核心邏輯
    const useTestQueueUI = create(...)      // UI 狀態
    
  3. API 快取

    // 實施 SWR 或 React Query
    const { data, error, mutate } = useSWR('/api/flashcards', fetcher)
    

7.3 中期重構 (1-2月)

  1. 微前端模組化

    // 按功能拆分獨立模組
    apps/
    ├── flashcards-module/
    ├── review-module/
    ├── generate-module/
    └── shell-app/
    
  2. 設計系統

    // 建立完整的設計系統
    components/
    ├── atoms/          # 原子組件
    ├── molecules/      # 分子組件
    ├── organisms/      # 有機體組件
    └── templates/      # 頁面模板
    
  3. 測試體系

    // 完整的測試覆蓋
    __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 + 業務邏輯
}

📊 雙層設計的價值

優點

  1. 關注點分離: Store 專注狀態Hook 專注邏輯
  2. 重用性: Store 可被多個 Hook 使用
  3. 可測試性: 可獨立測試狀態邏輯和業務邏輯
  4. 擴展性: 新功能容易添加新 Hook

缺點

  1. 學習成本: 開發者需理解兩層概念
  2. 複雜度: 簡單功能可能過度工程
  3. 調試難度: 狀態流向更複雜

🤔 是否過度設計?

分析

適合雙層的場景

  • 複習系統:複雜狀態 + 複雜邏輯
  • 詞卡管理:多種操作模式
  • 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 系統完整架構 建議更新頻率: 每月一次