差異 defineCachedEventHandler vs useFetch
在 Nuxt 開發中,defineCachedEventHandler 與 useFetch 是兩個完全不同層次的工具,分別處理「伺服器快取」與「資料抓取」。
快速對照表
| 特性 | defineCachedEventHandler | useFetch |
|---|---|---|
| 運行位置 | 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選項。
- 提示:這會影響 UI 判斷,若要保留舊資料,需使用
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。