Skip to content

差異 defineCachedEventHandler vs useFetch

在 Nuxt 開發中,defineCachedEventHandleruseFetch 是兩個完全不同層次的工具,分別處理「伺服器快取」與「資料抓取」。


快速對照表

特性defineCachedEventHandleruseFetch
運行位置Nitro Server (後端)Composables (前端/SSR)
主要用途快取 API 回應抓取並管理資料狀態
作用對象伺服器端的 API 邏輯Vue 組件內的資料
快取範圍全域共享 (所有使用者)單一請求/組件實例

1. defineCachedEventHandler (後端快取)

這是一個 Nitro 工具,用於 server/api。它會快取整個 API 的執行結果。

  • 目的:減少伺服器運算與資料庫查詢。
  • 特性:支援 SWR (Stale-While-Revalidate),可設定 maxAge
typescript
// server/api/data.ts
export default defineCachedEventHandler(async (event) => {
  return { date: new Date().toISOString() }
}, { maxAge: 60 })

2. useFetch (前端抓取)

這是 Vue 組件中使用的 Composable,用於發起請求並取得響應式資料。

  • 目的:將資料帶入組件,處理載入 (pending) 與錯誤 (error) 狀態。
  • 特性:在 SSR 期間抓取資料並傳遞給客戶端,避免重複請求。
vue
<script setup>
const { data, pending } = await useFetch('/api/data')
</script>

Nuxt 4 的重大差異

如果你使用 Nuxt 4 (或啟用了 Nuxt 4 相容模式),這兩者在使用上有以下關鍵變化:

1. useFetch 的預設行為改變 (Refetch)

  • Nuxt 3:重新抓取時會保留舊資料直到新資料抵達。
  • Nuxt 4:重新抓取時會立即清空舊資料 (data 變回 null)。
    • 提示:這會影響 UI 判斷,若要保留舊資料,需使用 getCachedData 選項。

2. 目錄結構

  • Nuxt 4 推薦將前端邏輯移至 app/ 目錄,而伺服器邏輯依然留在 server/
  • useFetch 會頻繁出現在 app/pages/ 中。

3. Nitro 引擎升級

  • defineCachedEventHandler 隨 Nitro v3 升級,提供了更強大的快取存儲層 (Storage Layers) 支援,且型別推導更精準。

使用 defineCachedEventHandler 的潛在風險

雖然快取能提升效能,但若使用不當會帶來以下問題:

1. 記憶體增加 (Memory Usage)

Nitro 預設將快取存在記憶體中 (memory storage)。

  • 風險:如果 API 回應量大且請求頻繁,伺服器記憶體會迅速被佔滿,導致 OOM (Out of Memory) 崩潰。
  • 對策:在生產環境建議設定外部儲存(如 Redis),或嚴格限制 maxAge

2. 資料過時 (Stale Data)

若資料更新頻率高,但快取時間設太長,使用者會看到舊資訊。

  • 對策:搭配 swr: true (Stale-While-Revalidate),讓使用者先看到舊資料,同時伺服器在背景靜默更新快取。

3. 身分驗證與隱私 (Security)

這是最常見的錯誤:快取了具有「使用者資訊」的 API。

  • 風險:如果沒有在 getKey 中加入使用者的標識(如 User ID),使用者 A 的個人資料可能會被快取並顯示給使用者 B。
  • 對策:對於具身分驗證的 API,應謹慎使用全域快取,或將 Authorization 資訊納入 Key 中。

總結:該選哪一個?

  • 想優化伺服器效能、讓所有人都變快:使用 defineCachedEventHandler
  • 想在頁面顯示資料、處理 UI 載入狀態:使用 useFetch