增量靜態再生 (ISR)
增量靜態再生 (ISR) 讓您能夠
- 更新靜態內容,而無需重建整個網站
- 透過為大多數請求提供預先渲染的靜態頁面,來減少伺服器負載
- 確保正確的
cache-control
標頭自動新增至頁面 - 處理大量內容頁面,而不會有過長的
next build
時間
以下是一個最小範例
interface Post {
id: string
title: string
content: string
}
// Next.js will invalidate the cache when a
// request comes in, at most once every 60 seconds.
export const revalidate = 60
// We'll prerender only the params from `generateStaticParams` at build time.
// If a request comes in for a path that hasn't been generated,
// Next.js will server-render the page on-demand.
export const dynamicParams = true // or false, to 404 on unknown paths
export async function generateStaticParams() {
const posts: Post[] = await fetch('https://api.vercel.app/blog').then((res) =>
res.json()
)
return posts.map((post) => ({
id: String(post.id),
}))
}
export default async function Page({
params,
}: {
params: Promise<{ id: string }>
}) {
const id = (await params).id
const post: Post = await fetch(`https://api.vercel.app/blog/${id}`).then(
(res) => res.json()
)
return (
<main>
<h1>{post.title}</h1>
<p>{post.content}</p>
</main>
)
}
以下說明此範例的運作方式
- 在
next build
期間,會產生所有已知的部落格文章(在此範例中有 25 篇) - 對這些頁面 (例如
/blog/1
) 發出的所有請求都會被快取並立即呈現 - 經過 60 秒後,下一個請求仍然會顯示快取(過時)的頁面
- 快取會失效,並且在背景中開始產生頁面的新版本
- 成功產生後,Next.js 將顯示並快取更新後的頁面
- 如果請求
/blog/26
,Next.js 將隨需產生並快取此頁面
參考
路由區段設定
函式
範例
基於時間的重新驗證
這會在 /blog
上提取並顯示部落格文章列表。一小時後,此頁面的快取將在下次訪問頁面時失效。然後,在背景中,會產生具有最新部落格文章的頁面新版本。
interface Post {
id: string
title: string
content: string
}
export const revalidate = 3600 // invalidate every hour
export default async function Page() {
const data = await fetch('https://api.vercel.app/blog')
const posts: Post[] = await data.json()
return (
<main>
<h1>Blog Posts</h1>
<ul>
{posts.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
</main>
)
}
我們建議設定較長的重新驗證時間。例如,1 小時而不是 1 秒。如果您需要更高的精確度,請考慮使用隨需重新驗證。如果您需要即時資料,請考慮切換到動態渲染。
使用 revalidatePath
隨需重新驗證
對於更精確的重新驗證方法,請使用 revalidatePath
函式隨需使頁面失效。
例如,在新增文章後會呼叫此伺服器行為。無論您在伺服器元件中如何檢索資料,無論是使用 fetch
還是連線到資料庫,這都會清除整個路由的快取,並允許伺服器元件提取最新的資料。
'use server'
import { revalidatePath } from 'next/cache'
export async function createPost() {
// Invalidate the /posts route in the cache
revalidatePath('/posts')
}
使用 revalidateTag
隨需重新驗證
對於大多數用例,建議優先重新驗證整個路徑。如果您需要更精細的控制,可以使用 revalidateTag
函式。例如,您可以標記個別的 fetch
呼叫
export default async function Page() {
const data = await fetch('https://api.vercel.app/blog', {
next: { tags: ['posts'] },
})
const posts = await data.json()
// ...
}
如果您正在使用 ORM 或連線到資料庫,則可以使用 unstable_cache
import { unstable_cache } from 'next/cache'
import { db, posts } from '@/lib/db'
const getCachedPosts = unstable_cache(
async () => {
return await db.select().from(posts)
},
['posts'],
{ revalidate: 3600, tags: ['posts'] }
)
export default async function Page() {
const posts = getCachedPosts()
// ...
}
然後您可以在伺服器行為或路由處理器中使用 revalidateTag
'use server'
import { revalidateTag } from 'next/cache'
export async function createPost() {
// Invalidate all data tagged with 'posts' in the cache
revalidateTag('posts')
}
處理未捕獲的例外
如果在嘗試重新驗證資料時擲回錯誤,則最後一次成功產生的資料將繼續從快取中提供。在下一個後續請求中,Next.js 將重試重新驗證資料。深入瞭解錯誤處理。
自訂快取位置
快取和重新驗證頁面(使用增量靜態再生)使用相同的共用快取。當部署到 Vercel時,ISR 快取會自動持久化到持久儲存體。
當自行託管時,ISR 快取會儲存到 Next.js 伺服器上的檔案系統(磁碟上)。當使用 Pages Router 和 App Router 自行託管時,這會自動運作。
如果您想要將快取的頁面和資料持久化到持久儲存體,或在 Next.js 應用程式的多個容器或實例之間共用快取,則可以設定 Next.js 快取位置。深入瞭解。
疑難排解
在本地開發中偵錯快取資料
如果您正在使用 fetch
API,則可以新增額外的記錄,以瞭解哪些請求已快取或未快取。深入瞭解 logging
選項。
module.exports = {
logging: {
fetches: {
fullUrl: true,
},
},
}
驗證正確的生產環境行為
若要驗證您的頁面在生產環境中是否已正確快取和重新驗證,您可以在本地透過執行 next build
,然後執行 next start
來執行生產環境 Next.js 伺服器進行測試。
這將允許您測試 ISR 行為,使其如同在生產環境中運作一樣。為了進一步偵錯,請將以下環境變數新增至您的 .env
檔案
NEXT_PRIVATE_DEBUG_CACHE=1
這會使 Next.js 伺服器控制台記錄 ISR 快取命中和未命中。您可以檢查輸出,以查看哪些頁面在 next build
期間產生,以及當隨需存取路徑時頁面如何更新。
注意事項
- 僅在使用 Node.js 執行階段(預設)時才支援 ISR。
- 建立靜態匯出時,不支援 ISR。
- 如果您在靜態渲染的路由中有多個
fetch
請求,並且每個請求都有不同的revalidate
頻率,則 ISR 將使用最短的時間。但是,這些重新驗證頻率仍將受到資料快取的尊重。 - 如果路由上使用的任何
fetch
請求的revalidate
時間為0
,或明確的no-store
,則路由將會動態渲染。 - 中介層不會針對隨需 ISR 請求執行,這表示中介層中的任何路徑重寫或邏輯都不會套用。請確保您正在重新驗證確切的路徑。例如,
/post/1
而不是重寫的/post-1
。
版本歷史
版本 | 變更 |
---|---|
v14.1.0 | 自訂 cacheHandler 功能已穩定。 |
v13.0.0 | 引入 App Router。 |
v12.2.0 | Pages Router:隨需 ISR 功能已穩定 |
v12.0.0 | Pages Router:新增Bot 感知 ISR 回退。 |
v9.5.0 | Pages Router:引入穩定的 ISR。 |
這有幫助嗎?