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

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

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

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

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

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

- 首次呼叫
fetch
請求時,資料會從外部資料來源獲取並儲存在資料快取中。 - 當觸發按需重新驗證時,相應的快取條目會從快取中清除。
- 這與基於時間的重新驗證不同,後者會在獲取新資料前保留過期資料。
- 下一次請求時,會再次是快取
MISS
,資料會從外部資料來源獲取並儲存在資料快取中。
選擇退出
如果您不想快取 fetch
的回應,可以這樣做:
完整路由快取
相關術語:
您可能會看到 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 Server Components 樹的緊湊二進制表示。React 在客戶端使用它來更新瀏覽器的 DOM。React Server Component Payload 包含:
- 伺服器元件的渲染結果
- 客戶端元件應渲染位置的佔位符及其 JavaScript 檔案的參考
- 從伺服器元件傳遞到客戶端元件的任何 props
要了解更多,請參閱伺服器元件文件。
2. Next.js 伺服器快取(完整路由快取)

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

了解更多關於靜態與動態渲染的資訊。
持續時間 (Duration)
預設情況下,完整路由快取 (Full Route Cache) 是持久性的。這意味著渲染輸出會在使用者請求之間被快取。
失效機制 (Invalidation)
有兩種方式可以讓完整路由快取失效:
- 重新驗證資料 (Revalidating Data):重新驗證資料快取 (Data Cache) 會連帶使路由快取 (Router Cache) 失效,透過在伺服器重新渲染元件並快取新的渲染輸出。
- 重新部署 (Redeploying):與資料快取不同(資料快取會在部署之間保留),完整路由快取會在每次新部署時被清除。
選擇退出 (Opting out)
您可以選擇退出完整路由快取,換句話說,針對每個傳入的請求動態渲染元件,方法如下:
- 使用動態 API (Dynamic API):這會讓路由退出完整路由快取,並在請求時動態渲染。資料快取仍可使用。
- 使用
dynamic = 'force-dynamic'
或revalidate = 0
路由區段設定選項:這會跳過完整路由快取和資料快取。意味著元件會在每個傳入的伺服器請求時重新渲染並重新取得資料。路由快取 (Router Cache) 仍會生效,因為它是客戶端快取。 - 選擇退出資料快取 (Data Cache):如果路由有一個未快取的
fetch
請求,這會讓路由退出完整路由快取。針對每個傳入的請求,會重新取得該特定fetch
請求的資料。其他未選擇退出快取的fetch
請求仍會被快取在資料快取中。這允許快取與非快取資料的混合使用。
客戶端路由快取 (Client-side Router Cache)
Next.js 有一個記憶體內的客戶端路由快取,用於儲存路由區段的 RSC 負載 (RSC payload),這些區段按佈局 (layouts)、載入狀態 (loading states) 和頁面 (pages) 分割。
當使用者在路由之間導航時,Next.js 會快取已造訪的路由區段,並預取 (prefetch) 使用者可能導航的路由。這實現了即時的返回/前進導航、導航之間無需完整頁面重新載入,並保留 React 狀態和瀏覽器狀態。
使用路由快取時:
- 佈局 (Layouts) 會在導航時被快取並重複使用(部分渲染 (partial rendering))。
- 載入狀態 (Loading states) 會在導航時被快取並重複使用,以實現即時導航 (instant navigation)。
- 頁面 (Pages) 預設不會被快取,但在瀏覽器後退和前進導航時會被重複使用。您可以透過實驗性的
staleTimes
設定選項啟用頁面區段的快取。
須知:此快取專門適用於 Next.js 和伺服器元件 (Server Components),與瀏覽器的 bfcache 不同,儘管效果類似。
持續時間 (Duration)
快取儲存在瀏覽器的臨時記憶體中。兩個因素決定路由快取的持續時間:
- 工作階段 (Session):快取會在導航之間保留。但頁面重新整理時會被清除。
- 自動失效週期 (Automatic Invalidation Period):佈局和載入狀態的快取會在特定時間後自動失效。持續時間取決於資源是如何預取 (prefetched) 的,以及資源是否為靜態生成 (statically generated):
- 預設預取 (Default Prefetching) (
prefetch={null}
或未指定):動態頁面不會快取,靜態頁面快取 5 分鐘。 - 完整預取 (Full Prefetching) (
prefetch={true}
或router.prefetch
):靜態和動態頁面均快取 5 分鐘。
- 預設預取 (Default Prefetching) (
雖然頁面重新整理會清除所有快取區段,但自動失效週期僅影響從預取時間起的個別區段。
須知:實驗性的
staleTimes
設定選項可用於調整上述的自動失效時間。
失效機制 (Invalidation)
有兩種方式可以讓路由快取失效:
- 在伺服器動作 (Server Action) 中:
- 透過路徑 (
revalidatePath
) 或快取標籤 (revalidateTag
) 按需重新驗證資料。 - 使用
cookies.set
或cookies.delete
會讓路由快取失效,以防止使用 cookies 的路由變得過時(例如驗證)。
- 透過路徑 (
- 呼叫
router.refresh
會讓路由快取失效,並向伺服器發送新請求以取得目前路由。
選擇退出 (Opting out)
從 Next.js 15 開始,頁面區段預設為選擇退出。
須知:您也可以透過將
<Link>
元件的prefetch
屬性設為false
來選擇退出預取 (prefetching)。
快取互動 (Cache Interactions)
在設定不同的快取機制時,了解它們之間如何互動非常重要:
資料快取與完整路由快取 (Data Cache and Full Route Cache)
- 重新驗證或選擇退出資料快取會讓完整路由快取失效,因為渲染輸出依賴於資料。
- 讓完整路由快取失效或選擇退出不會影響資料快取。您可以動態渲染一個同時包含快取和非快取資料的路由。這在頁面大部分使用快取資料,但少數元件依賴需要即時取得的資料時非常有用。您可以動態渲染,而無需擔心重新取得所有資料對效能的影響。
資料快取與客戶端路由快取 (Data Cache and Client-side Router cache)
- 若要立即讓資料快取和路由快取失效,您可以在伺服器動作 (Server Action) 中使用
revalidatePath
或revalidateTag
。 - 在路由處理器 (Route Handler) 中重新驗證資料快取不會立即讓路由快取失效,因為路由處理器不綁定到特定路由。這意味著路由快取會繼續提供先前的負載,直到強制重新整理或自動失效週期結束。
API 參考 (APIs)
下表概述了不同的 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 伺服器元件負載 (RSC payload) 加入路由快取。
若要停用預取,您可以將 prefetch
屬性設為 false
。但這不會永久跳過快取,當使用者造訪路由時,路由區段仍會在客戶端被快取。
了解更多關於 <Link>
元件 的資訊。
router.prefetch
useRouter
鉤子的 prefetch
選項可用於手動預取路由。這會將 React 伺服器元件負載加入路由快取。
參閱 useRouter
鉤子 API 參考。
router.refresh
useRouter
鉤子的 refresh
選項可用於手動重新整理路由。這會完全清除路由快取,並向伺服器發送新請求以取得目前路由。refresh
不會影響資料快取或完整路由快取。
渲染結果會在客戶端進行協調,同時保留 React 狀態和瀏覽器狀態。
參閱 useRouter
鉤子 API 參考。
fetch
從 fetch
回傳的資料不會自動快取在資料快取中。
fetch
的預設快取行為(例如未指定 cache
選項時)等同於將 cache
選項設為 no-store
:
參閱 fetch
API 參考 以取得更多選項。
fetch options.cache
您可以透過將 cache
選項設為 force-cache
來讓個別 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
方法會重新驗證資料快取,進而讓完整路由快取失效。
有兩個地方可以使用 revalidatePath
,取決於您想達成的目標:
- 路由處理器 (Route Handlers) - 在第三方事件(例如 webhook)回應中重新驗證資料。
- 伺服器動作 (Server Actions) - 在使用者互動(例如表單提交、點擊按鈕)後重新驗證資料。
參閱 revalidatePath
API 參考 以取得更多資訊。
revalidatePath
與router.refresh
的差異:呼叫
router.refresh
會清除路由快取,並在伺服器上重新渲染路由區段,而不會讓資料快取或完整路由快取失效。差異在於
revalidatePath
會清除資料快取和完整路由快取,而router.refresh()
不會改變資料快取和完整路由快取,因為它是客戶端 API。
動態 API (Dynamic APIs)
動態 API 如 cookies
和 headers
,以及頁面中的 searchParams
屬性,依賴於執行階段的傳入請求資訊。使用它們會讓路由退出完整路由快取,換句話說,路由會被動態渲染。
cookies
在伺服器動作中使用 cookies.set
或 cookies.delete
會讓路由快取失效,以防止使用 cookies 的路由變得過時(例如反映驗證變更)。
參閱 cookies
API 參考。
路由區段設定選項
路由區段設定選項 (Route Segment Config) 可用於覆寫預設的路由區段設定,或當您無法使用 fetch
API 時(例如使用資料庫客戶端或第三方函式庫)。
以下路由區段設定選項會使完整路由快取 (Full Route Cache) 失效:
const dynamic = 'force-dynamic'
此設定選項會讓所有 fetch 請求跳過資料快取 (Data Cache)(等同於 no-store
):
const fetchCache = 'default-no-store'
更多進階選項請參閱 fetchCache
。
其他選項請參閱路由區段設定文件。
generateStaticParams
對於動態區段(例如 app/blog/[slug]/page.js
),由 generateStaticParams
提供的路徑會在建置時快取至完整路由快取中。在請求時,Next.js 也會在首次造訪時快取建置時未知的路徑。
若要在建置時靜態渲染所有路徑,請向 generateStaticParams
提供完整路徑列表:
若要在建置時靜態渲染部分路徑,並在執行時首次造訪時渲染其餘路徑,請回傳部分路徑列表:
若要在首次造訪時靜態渲染所有路徑,請回傳空陣列(建置時不會渲染任何路徑)或使用 export const dynamic = 'force-static'
:
須知事項: 即使回傳空陣列,您也必須從
generateStaticParams
回傳一個陣列。否則該路由將會被動態渲染。
若要停用請求時的快取,可在路由區段中加入 export const dynamicParams = false
選項。使用此設定選項時,僅會提供由 generateStaticParams
生成的路徑,其他路由將回傳 404 或進行匹配(適用於萬用路由)。
React cache
函式
React cache
函式可讓您記憶化函式的回傳值,讓您能多次呼叫同一個函式,但僅執行一次。
由於 fetch
請求會自動記憶化,您不需要用 React cache
包裹它。但當 fetch
API 不適用時(例如某些資料庫客戶端、CMS 客戶端或 GraphQL 客戶端),您可以使用 cache
手動記憶化資料請求。