Next.js use cache 完全指南:cacheLife 與 cacheTag 快取策略教學,打造秒開網站
Next.js 的快取策略在過去幾個版本改了又改,很多開發者(包括我自己)都被搞得有點暈。好消息是,從 Next.js 15 引入、16 正式穩定的 use cache 指令,終於給了我們一套清晰、可控的快取方案。今天就來完整拆解這套新系統。
Next.js 快取機制的演進
在講新東西之前,先快速回顧一下 Next.js 快取策略的演進:
- Pages Router 時代:getStaticProps(SSG)+ getServerSideProps(SSR)+ ISR
- App Router 初期:fetch 預設快取 + revalidate,但行為不直覺,被大量吐槽
- Next.js 15+:捨棄預設快取,改為明確的
use cache指令
這個轉變的核心理念是:快取應該是顯式的。開發者不該猜測框架幫你快取了什麼,而是自己明確宣告。如果你對 React Server Components 的渲染策略還不熟,建議先看看那篇基礎知識。
use cache 指令基礎用法
'use cache' 可以標記在三個層級:
1. 整個路由快取
// app/blog/[slug]/page.tsx
'use cache'
export default async function BlogPost({ params }) {
const post = await getPost(params.slug)
return <article>{post.content}</article>
}
2. 元件層級快取
// components/Sidebar.tsx
'use cache'
export async function Sidebar() {
const popular = await getPopularPosts()
return <aside>{/* 熱門文章列表 */}</aside>
}
3. 函式層級快取
async function getCategories() {
'use cache'
const res = await fetch('https://api.example.com/categories')
return res.json()
}
重要提醒:use cache 只能在 Server Components 或 Server Functions 中使用,不支援 Edge Runtime。
cacheLife:精準控制快取壽命
cacheLife 用三個時間屬性控制快取行為:
- stale:客戶端直接使用快取(不詢問伺服器)的時長
- revalidate:超過此時間,下一個請求觸發背景刷新
- expire:快取的最長存活時間
Next.js 內建了幾個常用 profile:
import { cacheLife } from 'next/cache'
async function getPost(slug) {
'use cache'
cacheLife('hours') // stale: 5min, revalidate: 1hr, expire: 1hr
// cacheLife('days') // stale: 5min, revalidate: 1day, expire: 1day
// cacheLife('weeks') // stale: 5min, revalidate: 1week, expire: 1month
return await fetchPost(slug)
}
自訂 Cache Profile
內建 profile 不夠用?可以在 next.config.ts 中自訂:
// next.config.ts
const nextConfig = {
experimental: {
cacheLife: {
editorial: {
stale: 3600, // 1 小時內直接用快取
revalidate: 14400, // 4 小時後背景刷新
expire: 604800, // 最長存活 1 週
},
product: {
stale: 300, // 5 分鐘
revalidate: 900, // 15 分鐘
expire: 86400, // 1 天
}
}
}
}
一個我覺得很實用的技巧:可以根據資料狀態動態選擇 profile:
async function getContent(slug) {
'use cache'
const content = await fetchContent(slug)
if (!content) {
cacheLife('minutes') // 找不到?短期快取,很快重試
return null
}
if (content.status === 'draft') {
cacheLife('seconds') // 草稿?幾乎不快取
} else {
cacheLife('days') // 已發布?長期快取
}
return content
}
cacheTag:按需精準失效
cacheTag 讓你為快取資料加上標籤,之後可以精準地讓特定快取失效:
import { cacheTag } from 'next/cache'
async function getPost(id) {
'use cache'
cacheTag(`post:${id}`, 'posts')
cacheLife('days')
return await fetchPost(id)
}
然後在 Server Action 或 API Route 中觸發失效:
import { revalidateTag } from 'next/cache'
revalidateTag('post:abc-123') // 只失效某一篇
revalidateTag('posts') // 失效所有文章列表
標籤有些限制要注意:每個標籤最長 256 字元,每個快取項目最多 128 個標籤。實務上綽綽有餘。
組合策略:時間 + 標籤
最佳實踐是同時使用 cacheLife 和 cacheTag:
cacheLife作為安全網:即使忘了主動失效,資料也不會永遠過期cacheTag作為精準武器:CMS 更新時立即刷新
實戰:部落格與電商的快取設計
以這個部落格平台為例,我的快取策略設計如下:
| 資料類型 | cacheLife | cacheTag | 原因 |
|---|---|---|---|
| 文章內容 | days | post:{id} | 很少變動,修改後立即更新 |
| 分類列表 | weeks | categories | 幾乎不變 |
| 熱門文章 | hours | popular | 需定期刷新 |
| 搜尋結果 | minutes | — | 時效性強 |
踩坑紀錄與注意事項
- 不支援 Edge Runtime:如果你用 Vercel Edge Functions,
use cache不能用 - 每次執行只能呼叫一次 cacheLife:如果有 if/else 分支,確保每個路徑只呼叫一次
- 巢狀 use cache 的行為:子元件的快取設定不會被父元件覆蓋,各自獨立
- 開發環境預設不快取:記得在 production build 測試快取行為
搭配 Turbopack 一起用的話,開發體驗會好很多。
結語
use cache + cacheLife + cacheTag 這套組合拳,終於讓 Next.js 的快取策略變得既強大又可控。不再需要猜測框架的預設行為,一切由開發者說了算。如果你正在把專案從 Pages Router 遷移到 App Router,或從 Next.js 多語系架構中處理多語快取,這套新 API 絕對能幫上大忙。
繼續閱讀
Next.js Turbopack 完整教學:Rust 驅動的打包工具設定與效能優化指南
相關文章
你可能也喜歡
探索其他領域的精選好文