iT邦幫忙

2026 iThome 鐵人賽

DAY 11
0

❯❯ mock server+typed client:前端不等後端的全速開發
Day 11 後端還沒好,但我一天都沒等

📍 流水線位置|入口 → flow → 型別 → 【mock】 → 測試 → UI → vibe → 上線
流水線位置|入口 → flow → 型別 → 【mock】 → 測試 → UI → vibe → 上線

前端最常卡住的不是 code 寫不出來,是等:等後端把端點交出來、等環境可以聯調、等出問題再拉群一起排查。一般的解法是先在畫面上塞假資料把版刻出來,等後端好了再回頭接。

婚禮系統開工那陣子,業務規格早就透過 Spec 定案,但真正的資料庫連一張表都還沒建。照這個劇本,我應該要開始等了。

但我一天都沒等,也沒塞假資料。上一站立好型別合約後,我順手把 Mock Server 架了起來,讓前端從第一天就全速開發。


假資料不寫在前端,直接開成真端點

常見的做法是把測試資料寫死在前端元件(Hardcoded Data)裡,畫面先動起來再說。我沒這樣做,原因很簡單:流水線後面的自動化測試全都必須對著真正的 HTTP 端點發請求,假資料埋在 client 裡,測試根本餵不到。所以 mock 一開始就開在真正的 Server 端點層。

這些 Mock 路由直接放在 server/api/ 下,跟未來的正式 API 端點共用同一套路徑結構。兩者唯一的差異,只在 Mock 端點把狀態暫存在 server/mock/data/ 的記憶體陣列裡(重啟就重置),不對實體資料庫做持久化寫入。

對前端來說,呼叫 Mock 端點跟呼叫正式 API 在通訊協定層沒有任何差別:同樣發標準 HTTP 請求、收回應,全程被型別合約管著。寫元件的時候,我完全不需要關心後端資料庫蓋到了哪裡。

當然,Mock 資料本身也得遵守型別合約與業務不變量。
拿接待帳號模組當例子:

// server/mock/data/accounts.ts
export interface MockReceptionAccount {
  // ...
  passwordHash: string // 空字串=未設密碼、不可登入(僅作名單管理)
}

export const mockReceptionAccounts: MockReceptionAccount[] = [
  { accountId: 'account-001', weddingId: 'wedding-001',
    username: 'reception-desk-1', passwordHash: '' },
]

passwordHash 空字串這種邊界值,我直接把業務意涵寫進欄位註解,免得日後出現「型別過了、業務邏輯卻對不上」的假資料。

軟體工程「Server 級 Mock 端點架構」圖解


所有請求只走一個出口

到前端這端,所有 API 請求會統一收進 app/api/ 進行封裝。
這是接待帳號模組的 API 客戶端實作片段:

export function listReceptionAccounts(
  weddingId: MaybeRefOrGetter<string>,
  options?: HttpGetOptions<ReceptionAccountListItem[]>,
) {
  return useHttp().get<ReceptionAccountListItem[]>(
    () => `/api/v1/weddings/${toValue(weddingId)}/reception-accounts`,
    options,
  )
}

UI 元件只能透過 listReceptionAccounts(weddingId) 這類介面發請求,不准在元件裡自己拼 URL、也不准直接呼叫原生的 Fetch API。這樣封裝有三個好處:

  • 集中化路由管理
    當端點路徑更換時,只需修改單一客戶端函式即可全域生效。

  • 型別安全驗證
    當 API 回應型別發生變動,TypeScript 編譯器能在第一時間自動攔截錯誤。

  • 統一交織點(AOP)
    不論是帶 Auth Header、處理 401 登入過期,還是全域 Error Handling,都在這層一次搞定。

Typed Client 網路請求架構圖

此外,在發送策略上也做了分工:資料讀取統一走 useFetch Hook(支援 SSR 狀態預載),寫入則用 $fetch(操作時機明確),避免伺服器端與客戶端渲染行為不一致。


資料庫還沒影,27 個頁面先完工

把 Mock Server 與 Typed Client 組合起來,前端進度就跟後端實體資料庫徹底解耦了。在實體資料庫建起來之前,我已經做完 27 個前端頁面,跑過超過 160 條 E2E 測試。

因為前後端都緊扣同一份合約,這批在 Mock 階段寫出來的 UI 程式碼與測試邏輯,未來切換至正式後端時可以維持運作。

把 Mock Server 排在前面,還有一個核心考量:替測試驅動開發(TDD)鋪路。自動化 E2E 測試要對著具體的 HTTP 端點發請求才能斷言;後端端點還沒交付前,Mock Server 就是測試運作的目標端點,「先寫測試、後實作 UI」的循環才轉得起來。

系統由 Mock 遷移至實體後端的具體實作,核心只需要切換全域設定檔中的環境變數 URL。完整的對接細節與實戰演練,Day 23 會拆給你看。

至於這套「假後端」驗證到底夠不夠真實?真的接上實體後端會不會當場露餡?明天就來回答。

🎒 最小一步|把後端還沒交付的 API 回應先寫成標準 JSON,用任何簡易 server 開出端點,你的前端今天就能對著真的 HTTP 請求開發。
📎 本篇證據|app/api/accounts.api.ts(client 端封裝原始片段)・server/mock/data/ (Mock 資料結構定義)


上一篇
Day 10 先立合約,再蓋房子:打造 SSOT 型別合約防線,連 Server Handler 都不放過
下一篇
Day 12 你整套都在跟假後端玩,真的一接不就露餡了
系列文
收到自己的紅色炸彈!婚期就是 Deadline:前端一人用 AI 規格流水線,30 天出貨婚禮 SaaS14
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言