解構前端系統設計:從全域架構到微觀元件的底層邏輯與實戰策略

當我們談論軟體工程與架構設計時,大家腦海中浮現的畫面通常是非常標準化的:後端如何承載每秒百萬次請求的龐大伺服器架構、如何設計完美的資料庫模型。在那個世界裡,對與錯的界限通常很明確。然而,當踏入前端系統設計(Frontend System Design)的世界時,那把用來衡量技術優劣的量尺,突然之間就變得非常模糊了。這往往讓許多技術實力堅強的工程師感到挫折。本篇文章將探討前端系統設計的底層邏輯,將龐雜的知識提煉為在實際開發與技術決策中,能夠精準發揮的清晰策略。

前端系統設計的兩大類型

前端系統設計主要涵蓋兩大範疇:

  1. 應用程式架構(Application Level):設計一個完整的 Web 應用,如 Facebook 動態消息、Google Docs、Netflix 影音平台。焦點在客戶端——應用程式架構、元件拆分、以及前端與伺服器的通訊方式。

  2. UI 元件設計(UI Components Level):從零設計一個高度互動的元件,如自動完成輸入框、Modal 對話方塊、日期選擇器。這考驗對元件 API 設計、狀態管理、無障礙支援與主題客製化的掌握度。

本文將依序深入這兩個範疇,最後帶入 RADIO 框架有結構地進行架構設計。

                    ┌──────────────────────────────────────┐
                    │      前端系統設計的兩大範疇             │
                    └──────────────────────────────────────┘
                                   │
            ┌──────────────────────┴──────────────────────┐
            ▼                                              ▼
┌───────────────────────┐                  ┌───────────────────────────┐
│ ① 應用程式架構         │                  │ ② UI 元件設計              │
│ Application Level     │                  │ UI Components Level       │
├───────────────────────┤                  ├───────────────────────────┤
│ • 設計完整 Web 應用    │                  │ • 從零打造高度互動元件      │
│ • 焦點在客戶端架構     │                  │ • 元件 API / 狀態 / a11y   │
│ • 前端↔伺服器通訊      │                  │ • 主題客製化               │
│                       │                  │                           │
│ 範例:Facebook         │                  │ 範例:Autocomplete         │
│       Google Docs     │                  │       Modal Dialog        │
│       Netflix         │                  │       Date Picker         │
└───────────────────────┘                  └───────────────────────────┘

前端系統設計的本質:一場全域思維的壓力測試

前端系統設計絕對不只是寫出會動的 JavaScript 程式碼。相反地,它是一場考驗工程師全域性思維的壓力測試。在瀏覽器這個充滿限制的沙盒環境中,必須同時戴上產品經理、設計師與資深工程師的帽子,在商業價值、使用者體驗(UX)以及技術架構之間取得動態平衡。

第一戰場:應用程式全域架構(Application Level)

傳統系統設計的戰場在伺服器與資料庫,而前端的戰場則完全在「客戶端」。如果說傳統桌面軟體就像是蓋一棟實體的圖書館,那現代 Web 應用程式就如同被要求在一個叫做瀏覽器的玻璃櫃裡,蓋出一座功能完全相同、甚至更靈活的「微型圖書館」。

1. 狀態管理與單向資料流的餐廳哲學

現代網頁應用程式(如 Gmail 或 ChatGPT)追求幾乎瞬間改變、無需重新整理的流暢互動。這背後是靠 JavaScript 在幕後透過非同步方式向遠端伺服器獲取資料,並精準替換網頁中需要改變的區塊。然而,這也讓客戶端的狀態(State)變得異常複雜。

在一個複雜的網頁中,如果任何一個按鈕都可以隨意修改全域資料,狀態很快就會變成一團混亂的「義大利麵(Spaghetti code)」。因此,我們必須引進架構模式。傳統軟體工程中的 MVC(Model-View-Controller)、MVVM(Model-View-ViewModel)等經典模式同樣適用於 Web 應用,而 React 生態系則進一步推廣了單向資料流 + Flux/Redux reducer 架構。這就像是餐廳的點餐系統:客人不能直接衝進廚房動鍋鏟,必須把訂單交給服務生,集中送到中控台,廚房做好菜之後,再按照固定的動線端出來。這種「單向資料流」強迫所有的資料更新都必須走同一條明確的管道,展現你對架構的掌控力。

以下是 MVC、MVVM 與 Flux/Redux 三種架構的資料流對比:

 MVC 模式(雙向)              MVVM 模式(雙向)            Flux/Redux 模式(單向)
┌──────────┐     ┌──────────┐  ┌──────────┐     ┌──────────┐  ┌──────────┐     ┌──────────┐
│  Controller │◄───►│   Model  │  │  ViewModel│◄───►│   Model  │  │   Action  │────►│ Dispatcher│
└──────────┘     └──────────┘  └──────────┘     └──────────┘  └──────────┘     └──────────┘
      ▲                           │                               │                  │
      │                           ▼                               ▼                  ▼
┌──────────┐                ┌──────────┐                    ┌──────────┐     ┌──────────┐
│   View   │                │   View   │                    │  Reducer │◄────│   Store   │
└──────────┘                └──────────┘                    └──────────┘     └──────────┘
(View 可直接讀取 Model,                                        │                  │
 Controller 協調雙向互動)            ▲                          ▼                  │
 (View 透過 ViewModel             │                    ┌──────────┐             │
  間接操作 Model)                  └────────────────────│   View   │◄────────────┘
                                                        └──────────┘

Flux/Redux 的單向資料流確保資料變更沿著 Action → Dispatcher → Store → View 的固定方向前進,View 不能直接修改 Store,必須發送 Action 來觸發變更。這種模式讓狀態變更的路徑變得可追蹤、可預測且易於除錯。

2. 拒絕「萬用檢查清單」,依核心價值進行動態優化

許多優秀的工程師在規劃架構時,最常見的死穴就是套用一套「萬用檢查清單」。不論專案背景是什麼,盲目地把 SEO、效能優化、離線支援等名詞全部塞進設計裡。這其實是分散開發資源與失焦的最快途徑。你必須根據產品的核心價值來決定架構優化的重點:

產品類型 / 範例 架構核心優化重點 非核心 / 應避免過度討論
電商與旅遊平臺
(Amazon, Airbnb)
SEO 搜尋引擎最佳化、首頁首載速度、伺服器端渲染 (SSR)
網頁多延遲幾秒或爬蟲抓不到資料,公司便會直接虧損。
即時雙向通訊協定
即時通訊軟體
(Messenger, Slack)
即時通訊協定 (WebSocket)
建立持續開啟的雙向通道,伺服器收到新訊息能主動推送到畫面上,避免瀏覽器輪詢癱瘓後端。
SEO 最佳化
(私人訊息不應被 Google 索引)
無限滾動圖片串流
(Pinterest)
瀑布流佈局 (Masonry Layout) + 虛擬滾動 (Virtualization)
採用非等高的瀑布流柵格排列圖片,搭配虛擬滾動只渲染可視區域與預載範圍,釋放離開視線的圖片記憶體。
複雜狀態衝突解決模式
協作編輯應用
(Google Docs, Notion)
即時協作協定 + 衝突解決演算法
多人同時編輯同一份文件時,必須透過 OT (Operational Transformation) 或 CRDT 演算法合併變更,確保最終一致性。
SEO 最佳化(文件不應被公開索引)
影音串流平台
(Netflix, YouTube)
串流協定與媒體最佳化
實作串流傳輸(如 HLS 或 MPEG-DASH)、適應性位元速率(ABR)、以及影片播放器 UI 控制。
複雜即時通訊協定

決策邏輯可以濃縮為下圖:先辨識產品類別,再由類別推導出核心優化方向:

                        ┌──────────────────┐
                        │   這是什麼產品?    │
                        └──────────────────┘
                                 │
          ┌──────────────────────┼──────────────────────┐
          │                      │                      │
          ▼                      ▼                      ▼
┌──────────────────┐  ┌──────────────────┐  ┌──────────────────┐
│  電商 / 旅遊      │  │  即時通訊         │  │  協作編輯         │
│  Amazon, Airbnb   │  │  Messenger, Slack │  │  Google Docs      │
└──────────────────┘  └──────────────────┘  └──────────────────┘
          │                      │                      │
          ▼                      ▼                      ▼
┌──────────────────┐  ┌──────────────────┐  ┌──────────────────┐
│  SEO + SSR       │  │  WebSocket       │  │  OT / CRDT       │
│  效能            │  │  即時推播         │  │  衝突解決         │
└──────────────────┘  └──────────────────┘  └──────────────────┘

┌──────────────────┐  ┌──────────────────┐  ┌──────────────────┐
│  圖片串流         │  │  影音串流         │  │  其餘產品         │
│  Pinterest       │  │  Netflix, YouTube│  │  一般 Web App     │
└──────────────────┘  └──────────────────┘  └──────────────────┘
          │                      │                      │
          ▼                      ▼                      ▼
┌──────────────────┐  ┌──────────────────┐  ┌──────────────────┐
│  Masonry Layout  │  │  HLS / MPEG-DASH │  │  狀態管理         │
│  Virtualization  │  │  ABR             │  │  基本效能         │
└──────────────────┘  └──────────────────┘  └──────────────────┘

3. 其他常見架構深探主題

除了狀態管理與產品優化策略,以下跨領域主題也經常需要一併考量:

客戶端路由與程式碼拆分:SPA 如何在不重新載入頁面的情況下切換視圖?需要討論前端路由實作(hash-based vs history API)、動態導入(dynamic import)與程式碼拆分(code splitting)、以及預載(prefetch)策略。

API 層設計:前端與後端的通訊方式會直接影響架構複雜度。需要權衡 RESTful API、GraphQL 與 tRPC 的取捨——REST 簡單直覺但可能 over-fetching,GraphQL 彈性高但增加快取難度,tRPC 型別安全但僅限 TypeScript 生態。

快取策略:除了 HTTP 快取(Cache-Control、ETag),Service Worker 可用於實作離線支援與自訂快取策略(Cache First、Network First、Stale While Revalidate)。對於重複資料(如通訊錄、產品列表),客戶端記憶體快取(In-memory Cache)搭配正規化儲存(Normalized Store)是常見手法。

測試策略:前端測試需要在不同層級取得平衡——元件測試驗證 UI 邏輯、整合測試確保功能流程、E2E 測試覆蓋關鍵使用者路徑。應根據產品類型說明測試金字塔的取捨。

第二戰場:使用者介面元件設計(UI Components Level)

當我們需要從零手刻一個看似簡單的元件(如自動完成輸入框、下拉選單、對話方塊、日期選擇器)時,往往會考倒一大票習慣直接套用現成元件庫(如 Material UI)的開發者。我們真正要瞄準的,其實是針對高度互動性高度無障礙性的複雜元件。一個優秀的元件設計必須撐起以下四大支柱:

  1. 定義外部 API:釐清元件應該接收什麼 Props 或 Callback,這決定了其他開發者使用該元件時的體驗與擴充性。
  2. 內部狀態與元件層級:清楚交代元件內部的狀態管理以及子元件之間的層級互動關係(例如圖片輪播元件包含當前索引、分頁按鈕與預覽縮圖)。
  3. 無障礙設計(Accessibility / a11y):這是區分資深工程師與一般工程師的絕對分水嶺。以對話方塊(Modal/Dialog)為例:
   ┌──────────────────────────────────────────┐
   │           背後的網頁(半透明遮罩)          │
   │                                          │
   │   ┌────────────────────────────────┐      │
   │   │         Modal Dialog           │      │
   │   │                                │      │
   │   │  ╔══ 焦點陷阱 (Focus Trap) ══╗ │      │
   │   │  ║                          ║ │      │
   │   │  ║   [確認] ◄─────► [取消]  ║ │      │
   │   │  ║      ▲         ▲         ║ │      │
   │   │  ║      └────┬────┘         ║ │      │
   │   │  ║    Tab 循環鎖在 Modal 內  ║ │      │
   │   │  ╚══════════════════════════╝ │      │
   │   │                                │      │
   │   └────────────────────────────────┘      │
   │                                          │
   │   ❌ Tab 無法跳至此處(被遮罩攔截)        │
   └──────────────────────────────────────────┘

當視窗彈出時,必須實作焦點陷阱(Focus Trap),強迫鍵盤焦點只能在對話方塊內部的按鈕之間循環,避免視障使用者在使用螢幕閱讀器時,焦點跑到背後被遮住的網頁中。同時,必須加上正確的 ARIA 語義標籤(如 role="dialog"aria-modal="true"aria-labelledby)。

  1. 客製化主題機制(Customization & Theme):預留樣式與主題的擴充空間,讓元件能輕易替換顏色與字型,符合不同品牌的視覺規範。常見做法包括 CSS 變數(Custom Properties)slot propsrender props 模式,讓元件消費端能靈活覆蓋預設樣式。

以下是一個圖片輪播元件的簡化範例,展示元件層級與 Props 介面:

<ImageCarousel
  images={images}
  onPrev={handlePrev}
  onNext={handleNext}
  layout="horizontal"
  theme=
>
  <ImageCarouselImage
    image={currentImage}
    objectFit="cover"
  />
  <ImageThumbnail
    images={images}
    activeIndex={currentIndex}
    onClick={handleThumbnailClick}
  />
</ImageCarousel>

畫出這樣的元件樹就能清楚展示你對元件拆分與 API 設計的思考:

ImageCarousel              ← 容器元件:管理 currentIndex 狀態
│
│ props: images, onPrev, onNext, layout, theme
│
├── ImageCarouselImage     ← 顯示當前圖片
│   │ props: image, objectFit
│   │
│   └── <img>              ← 原生 HTML 元素
│
├── PaginationDots         ← 分頁指示器
│   │ props: total, activeIndex
│   │
│   └── <button> * N       ← 每個圓點對應一張圖片
│
└── ImageThumbnail         ← 預覽縮圖列
    │ props: images, activeIndex, onClick
    │
    └── <img> * N          ← 可點擊的小縮圖

元件設計的核心思維是:容器元件掌管狀態邏輯,展示元件只負責渲染

不可忽視的邊界狀態與效能考量

除了正常流程,以下是架構設計中常見的邊界情境:

主動提出這些 edge case 的處理方式,能展現對生產環境品質的深刻理解。

實戰破局:利用 RADIO 框架建立設計結構

架構設計的本質是在模糊不清的狀態下建立結構。面對龐雜的需求,我們需要一套結構化的推導框架,也就是 RADIO Framework。無論是應用程式架構還是 UI 元件設計,RADIO 都是核心架構決策骨架:

  ┌──────────────────────────────────────────────────┐
  │                    RADIO                          │
  │         前端系統設計架構框架                         │
  └──────────────────────────────────────────────────┘
          │         │         │         │         │
          ▼         ▼         ▼         ▼         ▼
  ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
  │   R      │ │   A      │ │   D      │ │   I      │ │   O      │
  │Requirements│ │Architecture│ │ Data Model│ │ Interface │ │Optimizat.│
  └──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘
       │            │            │            │            │
       ▼            ▼            ▼            ▼            ▼
  ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
  │需求收斂   │ │高階架構   │ │資料模型   │ │介面設計   │ │關鍵優化   │
  ├──────────┤ ├──────────┤ ├──────────┤ ├──────────┤ ├──────────┤
  │對齊範疇   │ │畫大區塊   │ │正規化     │ │API 規格   │ │核心價值   │
  │界定邊界   │ │定義界線   │ │ID 對應    │ │Props     │ │懶加載     │
  │功能取捨   │ │資料流向   │ │避免不一致  │ │型別定義   │ │樂觀更新   │
  └──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘

RADIO 框架的每個步驟的具體應用:

RADIO 實戰演練:以「設計 Facebook News Feed」為例

讓我們用 RADIO 框架快速走一遍應用程式架構題:

Step 1 ─ R (Requirements)
        • 支援貼文列表、無限滾動、按讚留言
        • 貼文包含文字、圖片、影片
        • 不討論即時通知(避免失焦)

Step 2 ─ A (Architecture)
        ┌──────────┐     ┌──────────┐     ┌──────────┐
        │  API Layer│────►│ Store     │────►│   View    │
        │(GraphQL) │     │(Redux)   │     │ (React)   │
        └──────────┘     └──────────┘     └──────────┘
               │               │
               ▼               ▼
        ┌──────────┐     ┌──────────┐
        │  Server  │     │  Cache   │
        └──────────┘     └──────────┘

Step 3 ─ D (Data Model)
        { post: { id, authorId, content, media[], likes, comments[] } }
        { user: { id, name, avatar } } ← 正規化,避免資料不一致

Step 4 ─ I (Interface)
        • API: feedPosts(after cursor, limit) → { posts[], cursor }
        • Component: <Feed>, <PostCard>, <LikeButton>, <CommentSection>

Step 5 ─ O (Optimizations)
        • 無限滾動 + 虛擬滾動(只渲染可視區域)
        • 圖片懶加載 + 預載下一頁(prefetch next cursor)
        • 按讚採樂觀更新(先改 UI,API 失敗再回滾)

只要按照 RADIO 的順序走完這五步,就能穩定展現完整的架構思考過程,避免卡在某個細節而偏離主軸。

上述 News Feed 屬於系統架構範例,展示 RADIO 在應用程式層級的巨觀設計;以下 Autocomplete 則屬於元件範例,展示 RADIO 在 UI 元件層級的微觀設計。兩種尺度皆能用同一套框架駕馭。

RADIO 實戰演練:以「設計 Autocomplete 元件」為例

Step 1 ─ R (Requirements)
        • 使用者在輸入框中打字,即顯示建議選項的下拉選單
        • 支援鍵盤導航:↑ ↓ 移動高亮、Enter 選取、Esc 關閉
        • 輸入需有 debounce 控制請求頻率
        • 支援非同步 API 與本地資料兩種模式
        • 涵蓋四種狀態:正常結果 / 載入中 / 無結果 / 錯誤
        • 排除:多選 tags、語音輸入、無限滾動

Step 2 ─ A (Architecture)

        ┌────────────────────────────────────────┐
        │              Autocomplete                │
        │  ┌──────────┐  ┌──────────────┐  ┌────┐ │
        │  │   Input   │  │useAutocomplete│  │Dropdown│ │
        │  │Component  │◄─┤    Hook      ├─►│ List │ │
        │  └──────────┘  └──────┬───────┘  └────┘ │
        │                       │                  │
        │                 ┌─────▼──────┐           │
        │                 │  Fetcher   │           │
        │                 │ (debounced)│           │
        │                 └────────────┘           │
        └────────────────────────────────────────┘

        Input Component:只負責渲染 <input> 與事件綁定
        useAutocomplete Hook:掌管所有狀態邏輯
        Fetcher:處理 debounce、API 呼叫、快取查詢
        Dropdown List:只負責渲染選項列表與高亮

Step 3 ─ D (Data Model)

        // 元件內部狀態
        type AutocompleteState = {
          query: string;              // 目前輸入文字
          results: Suggestion[];      // 回傳的建議清單
          isLoading: boolean;         // 是否載入中
          error: Error | null;        // 錯誤資訊
          highlightedIndex: number;   // 鍵盤高亮位置(-1 = 無)
          isOpen: boolean;            // 下拉選單是否展開
        };

        type Suggestion = {
          id: string;
          label: string;
          description?: string;
          icon?: string;
        };

        // 查詢快取:避免重複請求
        const queryCache = new Map<string, Suggestion[]>();
        // 上限 50 筆,超過時淘汰最舊的(LRU 策略)

Step 4 ─ I (Interface)

        // 元件 Props 介面
        type AutocompleteProps<TSuggestion> = {
          fetchFn: (query: string) => Promise<TSuggestion[]>;
          onSelect: (item: TSuggestion) => void;
          placeholder?: string;
          debounceMs?: number;        // 預設 300
          maxResults?: number;        // 預設 50
          renderOption?: (
            item: TSuggestion,
            isHighlighted: boolean
          ) => React.ReactNode;
        };

        // ARIA 無障礙標籤(combobox pattern)
        // <input role="combobox" aria-expanded aria-controls aria-activedescendant>
        // <ul role="listbox" id="listbox-id">
        //   <li role="option" aria-selected>

        // 使用範例
        function CityAutocomplete() {
          return (
            <Autocomplete
              fetchFn={searchCities}
              onSelect={(city) => navigate(`/city/${city.id}`)}
              placeholder="搜尋城市..."
              debounceMs={300}
              maxResults={20}
            />
          );
        }

Step 5 ─ O (Optimizations)

        ──── ① Debounce ────

        沒 debounce:
          使 → API    使用 → API    使用者正... → API    ← 3 次請求浪費

        有 debounce (300ms):
          使用者正在搜尋城市...(停頓 300ms) → API    ← 只 1 次

        function useDebounce<T>(value: T, delay: number): T {
          const [debounced, setDebounced] = useState(value);
          useEffect(() => {
            const timer = setTimeout(() => setDebounced(value), delay);
            return () => clearTimeout(timer);
          }, [value, delay]);
          return debounced;
        }

        ──── ② 請求快取 ────

        // LRU 快取:避免重複查詢同一關鍵字
        class LRUCache<K, V> {
          private cache = new Map<K, V>();
          constructor(private maxSize: number) {}

          get(key: K): V | undefined {
            if (!this.cache.has(key)) return undefined;
            const value = this.cache.get(key)!;
            this.cache.delete(key);     // 移至最新
            this.cache.set(key, value);
            return value;
          }

          set(key: K, value: V): void {
            if (this.cache.size >= this.maxSize) {
              const firstKey = this.cache.keys().next().value;
              this.cache.delete(firstKey);  // 淘汰最舊
            }
            this.cache.set(key, value);
          }
        }

        ──── ③ 取消前次請求 ────

        競態條件範例:使用者先打「台」,再打「台北車站」
        若「台」的回傳比「台北車站」晚到,選單會閃爍

        useEffect(() => {
          const controller = new AbortController();
          fetchFn(debouncedQuery, { signal: controller.signal })
            .then(setResults)
            .catch((err) => {
              if (err.name !== 'AbortError') setError(err);
            });
          return () => controller.abort();  // 前次請求作廢
        }, [debouncedQuery]);

        ──── ④ 鍵盤導航與焦點管理 ────

        const handleKeyDown = (e: React.KeyboardEvent) => {
          switch (e.key) {
            case 'ArrowDown':
              setHighlighted((prev) => Math.min(prev + 1, results.length - 1));
              break;
            case 'ArrowUp':
              setHighlighted((prev) => Math.max(prev - 1, -1));
              break;
            case 'Enter':
              if (highlightedIndex >= 0) onSelect(results[highlightedIndex]);
              break;
            case 'Escape':
              setIsOpen(false);
              break;
          }
        };

        // Click outside 關閉
        useEffect(() => {
          const handler = (e: MouseEvent) => {
            if (!ref.current?.contains(e.target as Node)) setIsOpen(false);
          };
          document.addEventListener('mousedown', handler);
          return () => document.removeEventListener('mousedown', handler);
        }, []);

         ──── ⑤ 大量結果虛擬滾動 ────

         若建議結果超過 50 筆,實作 VirtualList
         只渲染可視區域的 <li>(約 8–10 筆),而非全部
         參考 react-window 或自訂虛擬滾動邏輯

        ──── ⑥ 安全性考量 ────

         若建議清單來自使用者輸入或外部 API,需防範 XSS:
         • 避免直接將建議內容用 dangerouslySetInnerHTML 渲染
         • 使用 textContent 而非 innerHTML 設定顯示文字
         • 對 API 回傳的建議內容做跳脫(escape)處理

從這兩個範例可以看出:RADIO 無論在巨觀的系統架構還是微觀的元件設計,都能提供一致的結構化路徑。

無論面對的是哪一類架構問題,RADIO 框架都能在有限的時間內建立清晰且完整的設計脈絡,有效展現結構化思維。

評估維度(Evaluation Axes)

在規劃架構時,可從以下四個維度檢視設計的完整性:

維度 關鍵問題
正確性 架構是否滿足所有功能需求?邊界狀態(loading / empty / error)是否都有涵蓋?
可維護性 元件拆分是否合理?資料流是否清晰?新人加入能快速理解嗎?
效能 首載速度如何?大量資料時會卡頓嗎?是否有做懶加載、虛擬滾動等優化?
可擴展性 需求增加時架構能否適應?新功能加入需要大改還是局部調整?

在設計過程中隨時用這四個維度檢視,能幫助及早發現盲點。

總結

前端系統設計沒有標準答案,重點是如何在模糊中建立結構。掌握以下三點,就能穩健應對:

  1. 分類先決:先判斷是 Application Level 還是 UI Components Level,不同類型有不同的設計節奏。
  2. 產品驅動:讓產品類型引導技術決策,而不是套用萬用清單。
  3. 框架護航:用 RADIO 框架維持設計結構,即使遇到不熟悉的主題也能展現系統性思維。

最終,無論 AI 工具如何演進,架構決策的本質始終是取捨——在有限的時間與資源下,做出最符合產品目標的選擇。

參考資料


前端系統設計面試 RADIO 攻略


front-end architecture Architecture Design Pattern