Next.js 中的快取機制
Next.js 透過快取渲染工作和資料請求,提升應用程式效能並降低成本。本頁深入探討 Next.js 的快取機制、可用的配置 API 以及它們之間的互動方式。
須知事項:本頁幫助您理解 Next.js 的底層運作,但並非使用 Next.js 的必備知識。Next.js 的快取策略大多由您的 API 使用方式決定,並預設提供最佳效能,無需或僅需極少配置。
概觀
以下是不同快取機制及其用途的高層次概覽:
機制 | 快取內容 | 位置 | 用途 | 持續時間 |
---|---|---|---|---|
請求記憶化 (Request Memoization) | 函數回傳值 | 伺服器 | 在 React 元件樹中重複使用資料 | 單次請求生命週期 |
資料快取 (Data Cache) | 資料 | 伺服器 | 跨使用者請求和部署儲存資料 | 持久性 (可重新驗證) |
完整路由快取 (Full Route Cache) | HTML 和 RSC 負載 | 伺服器 | 降低渲染成本並提升效能 | 持久性 (可重新驗證) |
路由快取 (Router Cache) | RSC 負載 | 客戶端 | 減少導航時的伺服器請求 | 使用者會話或基於時間 |
預設情況下,Next.js 會盡可能快取以提升效能並降低成本。這意味著路由會靜態渲染且資料請求會被快取,除非您選擇退出。下圖顯示了預設的快取行為:當路由在建置時靜態渲染,以及當靜態路由首次被訪問時。

快取行為會根據路由是靜態或動態渲染、資料是否被快取,以及請求是首次訪問還是後續導航而變化。根據您的使用情境,您可以為個別路由和資料請求配置快取行為。
請求記憶化 (Request Memoization)
React 擴展了 fetch
API,自動記憶化具有相同 URL 和選項的請求。這意味著您可以在 React 元件樹的多個位置呼叫相同的 fetch 函數,而實際上只會執行一次。

例如,如果您需要在路由中多處使用相同資料(如在 Layout、Page 和多個元件中),您不必在樹的頂層獲取資料並透過 props 傳遞。相反,您可以在需要資料的元件中直接獲取,而無需擔心因網路重複請求相同資料而影響效能。
請求記憶化的工作原理

- 在渲染路由時,首次呼叫特定請求時,其結果不會在記憶體中,因此會是快取
MISS
。 - 因此,函數會被執行,資料會從外部來源獲取,結果會儲存在記憶體中。
- 同一渲染過程中的後續請求函數呼叫會是快取
HIT
,資料會從記憶體中回傳,無需再次執行函數。 - 路由渲染完成後,記憶體會「重置」,所有請求記憶化條目會被清除。
須知事項:
- 請求記憶化是 React 的功能,而非 Next.js 的功能。此處提及是為了展示它與其他快取機制的互動。
- 記憶化僅適用於
fetch
請求中的GET
方法。- 記憶化僅適用於 React 元件樹,這意味著:
- 它適用於
generateMetadata
、generateStaticParams
、Layouts、Pages 和其他伺服器元件中的fetch
請求。- 它不適用於路由處理器 (Route Handlers) 中的
fetch
請求,因為它們不屬於 React 元件樹的一部分。- 對於不適合使用
fetch
的情況(如某些資料庫客戶端、CMS 客戶端或 GraphQL 客戶端),您可以使用 Reactcache
函數 來記憶化函數。
持續時間
快取持續時間為伺服器請求的生命週期,直到 React 元件樹完成渲染。
重新驗證
由於記憶化不跨伺服器請求共享且僅在渲染期間有效,因此無需重新驗證。
選擇退出
記憶化僅適用於 fetch
請求中的 GET
方法,其他方法如 POST
和 DELETE
不會被記憶化。此預設行為是 React 的優化,我們不建議選擇退出。
若要管理個別請求,您可以使用 AbortController
的 signal
屬性。然而,這不會讓請求退出記憶化,而是中止進行中的請求。
資料快取 (Data Cache)
Next.js 內建了資料快取,可持久化資料請求的結果,跨伺服器請求和部署。這是因為 Next.js 擴展了原生 fetch
API,允許伺服器上的每個請求設定自己的持久化快取語義。
須知事項:在瀏覽器中,
fetch
的cache
選項表示請求如何與瀏覽器的 HTTP 快取互動;在 Next.js 中,cache
選項表示伺服器端請求如何與伺服器的資料快取互動。
預設情況下,使用 fetch
的資料請求會被快取。您可以使用 fetch
的 cache
和 next.revalidate
選項來配置快取行為。
資料快取的工作原理

- 在渲染期間首次呼叫
fetch
請求時,Next.js 會檢查資料快取是否有快取的回應。 - 如果找到快取的回應,會立即回傳並記憶化。
- 如果未找到快取的回應,會向資料來源發出請求,結果儲存在資料快取中並記憶化。
- 對於非快取資料(如
{ cache: 'no-store' }
),總是從資料來源獲取結果並記憶化。 - 無論資料是否被快取,請求總是會被記憶化,以避免在 React 渲染過程中重複請求相同資料。
資料快取與請求記憶化的差異
雖然兩種快取機制都透過重複使用快取資料來提升效能,但資料快取跨請求和部署持久化,而記憶化僅在單次請求的生命週期內有效。
透過記憶化,我們減少了同一渲染過程中必須跨越網路界限(從渲染伺服器到資料快取伺服器,如 CDN 或邊緣網路)或資料來源(如資料庫或 CMS)的重複請求數量。透過資料快取,我們減少了對原始資料來源的請求數量。
持續時間
資料快取跨請求和部署持久化,除非您重新驗證或選擇退出。
重新驗證
快取資料可以透過兩種方式重新驗證:
- 基於時間的重新驗證:在一定時間後重新驗證資料並在新請求時更新。這適用於變更不頻繁且即時性不高的資料。
- 按需重新驗證:根據事件(如表單提交)重新驗證資料。按需重新驗證可以使用標籤或路徑方式一次重新驗證一組資料。這適用於需要盡快顯示最新資料的情況(如 headless CMS 的內容更新時)。
基於時間的重新驗證
要按時間間隔重新驗證資料,您可以使用 fetch
的 next.revalidate
選項設定資源的快取生命週期(以秒為單位)。
或者,您可以使用路由區段配置選項來配置區段中的所有 fetch
請求,或在不使用 fetch
的情況下進行配置。
基於時間的重新驗證的工作原理

- 首次呼叫帶有
revalidate
的fetch
請求時,資料會從外部資料來源獲取並儲存在資料快取中。 - 在指定時間範圍內(如 60 秒)的任何請求都會回傳快取的資料。
- 時間範圍過後,下一次請求仍會回傳快取的(已過期)資料。
- Next.js 會在背景觸發資料的重新驗證。
- 資料成功獲取後,Next.js 會用新資料更新資料快取。
- 如果背景重新驗證失敗,則保留先前的資料不變。
這類似於 stale-while-revalidate 行為。
按需重新驗證
資料可以透過路徑 (revalidatePath
) 或快取標籤 (revalidateTag
) 按需重新驗證。
按需重新驗證的工作原理

- 首次呼叫
fetch
請求時,資料會從外部資料來源獲取並儲存在資料快取中。 - 觸發按需重新驗證時,相應的快取條目會從快取中清除。
- 這與基於時間的重新驗證不同,後者會在獲取新資料前保留過期資料。
- 下次請求時會再次是快取
MISS
,資料會從外部資料來源獲取並儲存在資料快取中。
選擇退出
對於個別資料獲取,您可以透過將 cache
選項設為 no-store
來選擇退出快取。這意味著每次呼叫 fetch
時都會獲取資料。
或者,您也可以使用路由區段配置選項為特定路由區段選擇退出快取。這會影響區段中的所有資料請求,包括第三方函式庫。
注意:資料快取目前僅適用於頁面/路由,不適用於中介軟體 (middleware)。中介軟體中的任何
fetch
預設都不會被快取。
Vercel 資料快取
如果您的 Next.js 應用程式部署在 Vercel 上,建議閱讀 Vercel 資料快取 文件以更好地理解 Vercel 的特定功能。
完整路由快取 (Full Route Cache)
相關術語:
您可能會看到 Automatic Static Optimization、Static Site Generation 或 Static Rendering 這些術語交替使用,指在建置時渲染和快取應用程式路由的過程。
Next.js 會在建置時自動渲染和快取路由。這是一種優化,允許您提供快取的路由,而非每次請求時在伺服器上渲染,從而加快頁面載入速度。
要理解完整路由快取的工作原理,了解 React 如何處理渲染以及 Next.js 如何快取結果很有幫助:
1. 伺服器上的 React 渲染
在伺服器上,Next.js 使用 React 的 API 來協調渲染。渲染工作被拆分為區塊:按個別路由區段和 Suspense 邊界。
每個區塊的渲染分為兩個步驟:
- React 將伺服器元件渲染為一種特殊的資料格式,稱為 React Server Component Payload,專為串流優化。
- Next.js 使用 React Server Component Payload 和客戶端元件 JavaScript 指令在伺服器上渲染 HTML。
這意味著我們不必等待所有內容渲染完成後才快取工作或發送回應。相反,我們可以在工作完成時串流回應。
什麼是 React Server Component Payload?
React Server Component Payload 是渲染後的 React 伺服器元件樹的緊湊二進位表示。React 在客戶端使用它來更新瀏覽器的 DOM。React Server Component Payload 包含:
- 伺服器元件的渲染結果
- 客戶端元件應渲染位置的佔位符及其 JavaScript 檔案的參考
- 從伺服器元件傳遞給客戶端元件的任何 props
欲了解更多,請參閱 伺服器元件 文件。
2. Next.js 在伺服器上的快取 (完整路由快取)

Next.js 的預設行為是在伺服器上快取路由的渲染結果(React Server Component Payload 和 HTML)。這適用於建置時靜態渲染的路由,或在重新驗證期間。
3. 客戶端的 React 水合 (Hydration) 與協調 (Reconciliation)
在請求時,客戶端會進行以下步驟:
- 使用 HTML 立即顯示客戶端與伺服器元件的快速非互動式初始預覽。
- 使用 React 伺服器元件有效載荷 (Payload) 來協調客戶端與已渲染的伺服器元件樹,並更新 DOM。
- 使用 JavaScript 指令來水合 (hydrate) 客戶端元件,使應用程式具有互動性。
4. Next.js 在客戶端的快取機制 (路由快取 Router Cache)
React 伺服器元件有效載荷會儲存在客戶端的路由快取 (Router Cache) 中,這是一個獨立的記憶體快取,按個別路由區段分割。此路由快取用於儲存先前造訪過的路由並預取未來可能訪問的路由,從而提升導航體驗。
5. 後續導航
在後續導航或預取過程中,Next.js 會檢查 React 伺服器元件有效載荷是否已儲存在路由快取中。如果是,則會跳過向伺服器發送新請求。
如果路由區段不在快取中,Next.js 會從伺服器獲取 React 伺服器元件有效載荷,並在客戶端填充路由快取。
靜態與動態渲染
路由是否在構建時被快取取決於它是靜態渲染還是動態渲染。靜態路由預設會被快取,而動態路由則在請求時渲染,且不會被快取。
以下圖表展示了靜態與動態渲染路由的差異,以及快取與未快取資料的對比:

了解更多關於靜態與動態渲染的資訊。
持續時間
預設情況下,完整路由快取 (Full Route Cache) 是持久性的。這意味著渲染輸出會在使用者請求之間被快取。
失效機制
有兩種方式可以讓完整路由快取失效:
- 重新驗證資料 (Revalidating Data):重新驗證資料快取 (Data Cache) 會連帶使路由快取失效,因為伺服器會重新渲染元件並快取新的渲染輸出。
- 重新部署 (Redeploying):與資料快取不同(資料快取會在部署之間持續存在),完整路由快取會在每次新部署時被清除。
選擇退出
您可以選擇退出完整路由快取,換句話說,針對每個傳入的請求動態渲染元件,方法是:
- 使用動態函式 (Dynamic Function):這會讓路由退出完整路由快取,並在請求時動態渲染。資料快取仍可使用。
- 使用路由區段配置選項
dynamic = 'force-dynamic'
或revalidate = 0
:這會跳過完整路由快取和資料快取。意味著元件會在每次傳入請求時重新渲染,並從伺服器獲取資料。路由快取仍會生效,因為它是客戶端快取。 - 選擇退出資料快取 (Data Cache):如果路由有一個未快取的
fetch
請求,這會讓路由退出完整路由快取。針對該特定fetch
請求的資料會在每次傳入請求時重新獲取。其他未選擇退出快取的fetch
請求仍會被快取在資料快取中。這允許混合使用快取與未快取的資料。
路由快取 (Router Cache)
相關術語:
您可能會看到路由快取被稱為客戶端快取 (Client-side Cache) 或預取快取 (Prefetch Cache)。雖然預取快取指的是預取的路由區段,客戶端快取則是指整個路由快取,包括已造訪和預取的區段。 此快取專門適用於 Next.js 和伺服器元件,與瀏覽器的 bfcache 不同,儘管效果類似。
Next.js 有一個記憶體中的客戶端快取,用於儲存 React 伺服器元件有效載荷,按個別路由區段分割,並在使用者會話期間保留。這稱為路由快取。
路由快取的工作原理

當使用者在路由之間導航時,Next.js 會快取已造訪的路由區段,並預取 (prefetch) 使用者可能導航到的路由(基於其視窗中的 <Link>
元件)。
這為使用者帶來了更好的導航體驗:
- 即時的後退/前進導航,因為已造訪的路由被快取,且新路由的導航因預取和部分渲染 (partial rendering) 而快速。
- 導航之間無需完整頁面重新載入,且 React 狀態和瀏覽器狀態會被保留。
路由快取與完整路由快取的差異:
路由快取在使用者會話期間暫時將 React 伺服器元件有效載荷儲存在瀏覽器中,而完整路由快取則在多個使用者請求之間將 React 伺服器元件有效載荷和 HTML 持久儲存在伺服器上。
完整路由快取僅快取靜態渲染的路由,而路由快取同時適用於靜態與動態渲染的路由。
持續時間
快取儲存在瀏覽器的臨時記憶體中。兩個因素決定了路由快取的持續時間:
- 會話 (Session):快取在導航之間持續存在。但在頁面重新整理時會被清除。
- 自動失效週期 (Automatic Invalidation Period):佈局 (layouts) 和載入狀態的快取會在特定時間後自動失效。持續時間取決於資源是如何預取 (prefetched) 的,以及資源是否為靜態生成 (statically generated):
- 預設預取 (Default Prefetching) (
prefetch={null}
或未指定):動態頁面不會被快取,靜態頁面快取 5 分鐘。 - 完整預取 (Full Prefetching) (
prefetch={true}
或router.prefetch
):靜態與動態頁面均快取 5 分鐘。
- 預設預取 (Default Prefetching) (
雖然頁面重新整理會清除所有快取的區段,但自動失效週期僅影響從預取時間起的個別區段。
須知:實驗性的
staleTimes
配置選項可用於調整上述的自動失效時間。
失效機制
有兩種方式可以讓路由快取失效:
- 在伺服器操作 (Server Action) 中:
- 按路徑 (
revalidatePath
) 或快取標籤 (revalidateTag
) 按需重新驗證資料。 - 使用
cookies.set
或cookies.delete
會讓路由快取失效,以防止使用 cookies 的路由變得過時(例如驗證)。
- 按路徑 (
- 呼叫
router.refresh
會讓路由快取失效,並為當前路由向伺服器發送新請求。
選擇退出
無法完全選擇退出路由快取。但您可以通過呼叫 router.refresh
、revalidatePath
或 revalidateTag
(見上文)來讓它失效。這會清除快取並向伺服器發送新請求,確保顯示最新資料。
您也可以通過將 <Link>
元件的 prefetch
屬性設為 false
來選擇退出預取 (prefetching)。但這仍會暫時儲存路由區段 30 秒,以允許在嵌套區段(例如標籤欄)之間或前後導航時實現即時導航。已造訪的路由仍會被快取。
快取互動
在配置不同的快取機制時,了解它們如何相互影響非常重要:
資料快取與完整路由快取
- 重新驗證或選擇退出資料快取會讓完整路由快取失效,因為渲染輸出依賴於資料。
- 讓完整路由快取失效或選擇退出完整路由快取不會影響資料快取。您可以動態渲染一個同時包含快取和未快取資料的路由。這在頁面大部分使用快取資料,但少數元件依賴需要即時獲取的資料時非常有用。您可以動態渲染,無需擔心重新獲取所有資料對效能的影響。
資料快取與客戶端路由快取
- 在路由處理器 (Route Handler) 中重新驗證資料快取不會立即讓路由快取失效,因為路由處理器並不綁定到特定路由。這意味著路由快取會繼續提供先前的有效載荷,直到強制重新整理或自動失效週期結束。
- 要立即讓資料快取和路由快取失效,您可以在伺服器操作 (Server Action) 中使用
revalidatePath
或revalidateTag
。
API
以下表格概述了不同 Next.js API 如何影響快取:
API | 路由快取 (Router Cache) | 完整路由快取 (Full Route Cache) | 資料快取 (Data Cache) | React 快取 (React Cache) |
---|---|---|---|---|
<Link prefetch> | 快取 | |||
router.prefetch | 快取 | |||
router.refresh | 重新驗證 | |||
fetch | 快取 | 快取 | ||
fetch options.cache | 快取或選擇退出 | |||
fetch options.next.revalidate | 重新驗證 | 重新驗證 | ||
fetch options.next.tags | 快取 | 快取 | ||
revalidateTag | 重新驗證 (伺服器操作) | 重新驗證 | 重新驗證 | |
revalidatePath | 重新驗證 (伺服器操作) | 重新驗證 | 重新驗證 | |
const revalidate | 重新驗證或選擇退出 | 重新驗證或選擇退出 | ||
const dynamic | 快取或選擇退出 | 快取或選擇退出 | ||
cookies | 重新驗證 (伺服器操作) | 選擇退出 | ||
headers , searchParams | 選擇退出 | |||
generateStaticParams | 快取 | |||
React.cache | 快取 | |||
unstable_cache |
<Link>
預設情況下,<Link>
元件會自動從完整路由快取預取路由,並將 React 伺服器元件有效載荷添加到路由快取中。
要禁用預取,您可以將 prefetch
屬性設為 false
。但這不會永久跳過快取,當使用者造訪路由時,路由區段仍會被快取在客戶端。
了解更多關於 <Link>
元件 的資訊。
router.prefetch
useRouter
鉤子的 prefetch
選項可用於手動預取路由。這會將 React 伺服器元件有效載荷添加到路由快取中。
參閱 useRouter
鉤子 API 參考。
router.refresh
useRouter
鉤子的 refresh
選項可用於手動重新整理路由。這會完全清除路由快取,並為當前路由向伺服器發送新請求。refresh
不會影響資料快取或完整路由快取。
渲染結果會在客戶端進行協調,同時保留 React 狀態和瀏覽器狀態。
參閱 useRouter
鉤子 API 參考。
fetch
從 fetch
返回的資料會自動快取在資料快取中。
參閱 fetch
API 參考 以獲取更多選項。
fetch options.cache
您可以通過將 cache
選項設為 no-store
來讓個別 fetch
請求選擇退出資料快取:
由於渲染輸出依賴於資料,使用 cache: 'no-store'
也會讓使用該 fetch
請求的路由跳過完整路由快取。也就是說,該路由會在每次請求時動態渲染,但您仍可以在同一路由中使用其他快取的資料請求。
參閱 fetch
API 參考 以獲取更多選項。
fetch options.next.revalidate
您可以使用 fetch
的 next.revalidate
選項來設定個別 fetch
請求的重新驗證週期(以秒為單位)。這會重新驗證資料快取,進而重新驗證完整路由快取。會獲取新資料,並在伺服器上重新渲染元件。
參閱 fetch
API 參考 以獲取更多選項。
fetch options.next.tags
與 revalidateTag
Next.js 提供了一個快取標籤系統,用於實現細粒度的資料快取與重新驗證。
- 使用
fetch
或unstable_cache
時,您可以選擇用一個或多個標籤來標記快取項目。 - 接著,您可以呼叫
revalidateTag
來清除與該標籤相關的快取項目。
例如,您可以在獲取資料時設定標籤:
然後,呼叫 revalidateTag
並指定標籤以清除快取項目:
根據您的需求,可以在以下兩個地方使用 revalidateTag
:
- 路由處理器 (Route Handlers) - 用於在第三方事件(例如 Webhook)發生時重新驗證資料。這不會立即使路由快取失效,因為路由處理器並未綁定到特定路由。
- 伺服器操作 (Server Actions) - 用於在使用者操作(例如表單提交)後重新驗證資料。這將使相關路由的路由快取失效。
revalidatePath
revalidatePath
允許您手動重新驗證資料 並 在單一操作中重新渲染特定路徑下的路由區段。呼叫 revalidatePath
方法會重新驗證資料快取 (Data Cache),進而使完整路由快取 (Full Route Cache) 失效。
根據您的需求,可以在以下兩個地方使用 revalidatePath
:
- 路由處理器 (Route Handlers) - 用於在第三方事件(例如 Webhook)發生時重新驗證資料。
- 伺服器操作 (Server Actions) - 用於在使用者互動(例如表單提交、點擊按鈕)後重新驗證資料。
更多資訊請參閱 revalidatePath
API 參考文件。
revalidatePath
與router.refresh
的比較:呼叫
router.refresh
會清除路由快取 (Router Cache),並在伺服器上重新渲染路由區段,但不會使資料快取 (Data Cache) 或完整路由快取 (Full Route Cache) 失效。兩者的區別在於,
revalidatePath
會清除資料快取和完整路由快取,而router.refresh()
不會改變資料快取和完整路由快取,因為它是一個客戶端 API。
動態函式
動態函式如 cookies
和 headers
,以及 Pages 中的 searchParams
屬性,依賴於運行時傳入的請求資訊。使用這些函式會使路由退出完整路由快取 (Full Route Cache),換句話說,該路由將被動態渲染。
cookies
在伺服器操作 (Server Action) 中使用 cookies.set
或 cookies.delete
會使路由快取失效,以防止使用 cookies 的路由變得過時(例如反映認證狀態的變更)。
更多資訊請參閱 cookies
API 參考文件。
路由區段配置選項
路由區段配置選項可用於覆蓋路由區段的預設值,或在無法使用 fetch
API 時(例如使用資料庫客戶端或第三方函式庫)使用。
以下路由區段配置選項將使路由退出資料快取 (Data Cache) 和完整路由快取 (Full Route Cache):
const dynamic = 'force-dynamic'
const revalidate = 0
更多選項請參閱 路由區段配置 (Route Segment Config) 文件。
generateStaticParams
對於 動態路由區段 (dynamic segments)(例如 app/blog/[slug]/page.js
),由 generateStaticParams
提供的路徑會在構建時快取在完整路由快取 (Full Route Cache) 中。在請求時,Next.js 也會在首次訪問時快取那些在構建時未知的路徑。
您可以在路由區段中使用 export const dynamicParams = false
選項來禁用請求時的快取。當使用此配置選項時,只有由 generateStaticParams
提供的路徑會被服務,其他路由將返回 404 或匹配(在 萬用路由 (catch-all routes) 的情況下)。
更多資訊請參閱 generateStaticParams
API 參考文件。
React cache
函式
React cache
函式允許您記憶化函式的返回值,從而可以在多次呼叫同一函式時僅執行一次。
由於 fetch
請求會自動記憶化,您無需將其包裹在 React cache
中。然而,在 fetch
API 不適用的情況下,您可以使用 cache
手動記憶化資料請求。例如,某些資料庫客戶端、CMS 客戶端或 GraphQL 客戶端。