介紹
Next.js App Router 具有強大的快取架構,旨在優化載入速度並減少後端 API 開銷。
然而,由於 Next.js 整合了多個快取層,開發人員經常遇到除錯問題。常見問題包括頁面顯示陳舊資料或 API 觸發過於頻繁。
本文透過解釋 Next.js 中的四種快取機制以及配置、刷新和無效它們的技術來消除混亂。
1. Next.js App Router 的四個快取層
Next.js App Router 使用四個獨立的快取層:
[Client Side]
1. Router Cache (Temporary in-browser navigation cache)
│
[Server Side]
2. Request Memoization (React component render-cycle memory)
│
3. Data Cache (Persistent API request data across users)
│
4. Full Route Cache (Static HTML and RSC payloads at build-time)
以下總結各層的特色:
| 快取層 | 地點 | 快取內容 | 壽命 | 無效/重新生效 |
|---|---|---|---|---|
| 1.路由器快取 | 客戶 | RSC有效載荷 | 基於會話(分鐘) | router.refresh(),伺服器操作 |
| 2.請求記憶 | 伺服器 | fetch 回覆 | 單一渲染週期 | 依照請求自動清除 |
| 3.資料快取 | 伺服器 | API回應資料 | 堅持不懈 | revalidatePath、revalidateTag |
| 4.完整路由快取 | 伺服器 | HTML 與 RSC 有效負載 | 堅持不懈 | 重建,與資料快取相關 |
2. 每個快取層如何運作
① 請求記憶
如果在單一渲染請求期間在同一 React 元件樹中多次取得相同的 URL 和配置,則僅執行第一個請求。其餘呼叫從記憶緩存讀取。
// Component A
async function UserProfile() {
const res = await fetch('https://api.example.com/user'); // Fires API call
return <div>...</div>;
}
// Component B (rendered during the same cycle)
async function UserSettings() {
const res = await fetch('https://api.example.com/user'); // Reads from memoization cache
return <div>...</div>;
}
- 好處: 無需透過 props 向下傳遞資料。組件可以獨立取得自己的數據需求。
② 資料緩存
資料快取在傳入請求和多個使用者之間保留 API 回應資料。
預設情況下,Next.js 14 中的標準 fetch 請求快取在此處(注意:Next.js 15 預設為未快取的取得請求,儘管可以明確啟用快取)。
- 重新驗證: 您可以設定基於時間的 TTL 或觸發按需重新驗證:
// Revalidate cache after one hour (3600 seconds)
fetch('https://api.example.com/products', { next: { revalidate: 3600 } });
③ 全路由緩存
在建置時,Next.js 編譯頁面結構,呈現靜態 HTML 和 RSC 有效負載。這對應於靜態站點產生 (SSG)。
- 動態中斷:
如果 Next.js 偵測到動態函數(例如
cookies()、headers()或讀取動態searchParams),它會繞過完整路由快取。然後,該頁面會根據每個請求動態呈現。
④ 路由器快取
客戶端瀏覽器快取。當使用者在路線之間導航時,Next.js 會在記憶體中快取預取和造訪過的頁面。這使得即時來回導航成為可能。
- 無效:
在伺服器操作內觸發
revalidatePath會自動使路由器快取失效,確保使用者在下次導航時獲得更新的佈局。
3. 實用的快取設定秘訣
場景 A:即時資料(繞過伺服器快取)
對於顯示即時更新的頁面(例如財務圖表或即時狀態板),請停用 fetch 請求的快取:
const res = await fetch('https://api.example.com/live-ticks', {
cache: 'no-store'
});
或者,強制整個路線保持動態:
export const dynamic = 'force-dynamic';
場景 B:按需重新驗證 (revalidateTag)
對於在資料庫記錄變更(例如發布部落格文章)時立即更新快取內容非常有用。
// Append a tag to the fetch cache
const res = await fetch('https://api.example.com/posts', {
next: { tags: ['blog-posts'] }
});
// Trigger cache invalidation in a Server Action
import { revalidateTag } from 'next/cache';
async function updatePost() {
'use server';
await saveToDatabase();
// Clear all caches tagged with 'blog-posts'
revalidateTag('blog-posts');
}
結論
了解 Next.js 快取依賴於區分 Request Memoization(一個渲染請求)和 Data Cache(跨請求持續存在)的生命週期。
若要驗證快取設置,請在部署之前執行 next build 以檢查哪些路由編譯為靜態 (○),哪些路由編譯為動態 (λ)。

