如何實現增量靜態再生成 (ISR)
增量靜態再生成 (ISR) 使您能夠
- 更新靜態內容而無需重新構建整個網站
- 透過為大多數請求提供預渲染的靜態頁面來減少伺服器負載
- 確保頁面自動新增正確的
cache-control頭 - 處理大量內容頁面而無需漫長的
next build時間
這是一個最小示例
import type { GetStaticPaths, GetStaticProps } from 'next'
interface Post {
id: string
title: string
content: string
}
interface Props {
post: Post
}
export const getStaticPaths: GetStaticPaths = async () => {
const posts = await fetch('https://api.vercel.app/blog').then((res) =>
res.json()
)
const paths = posts.map((post: Post) => ({
params: { id: String(post.id) },
}))
return { paths, fallback: 'blocking' }
}
export const getStaticProps: GetStaticProps<Props> = async ({
params,
}: {
params: { id: string }
}) => {
const post = await fetch(`https://api.vercel.app/blog/${params.id}`).then(
(res) => res.json()
)
return {
props: { post },
// Next.js will invalidate the cache when a
// request comes in, at most once every 60 seconds.
revalidate: 60,
}
}
export default function Page({ post }: Props) {
return (
<main>
<h1>{post.title}</h1>
<p>{post.content}</p>
</main>
)
}此示例的工作原理如下
- 在
next build期間,所有已知的部落格文章都會被生成 - 所有對這些頁面的請求(例如
/blog/1)都會被快取並立即返回 - 60 秒過後,下一個請求仍將返回快取的(現已過時)頁面
- 快取失效,並在後臺開始生成頁面新版本
- 成功生成後,下一個請求將返回更新後的頁面並將其快取以供後續請求使用
- 如果請求
/blog/26且它存在,頁面將按需生成。此行為可以透過使用不同的fallback值來更改。但是,如果帖子不存在,則返回 404。
參考
函式
示例
使用 res.revalidate() 進行按需驗證
為了更精確地重新驗證,使用 res.revalidate 從 API 路由器按需生成一個新頁面。
例如,可以在 /api/revalidate?secret=<token> 呼叫此 API 路由,以重新驗證給定的部落格文章。建立一個只有您的 Next.js 應用程式知道的秘密令牌。此秘密將用於防止未經授權訪問重新驗證 API 路由。
import type { NextApiRequest, NextApiResponse } from 'next'
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
// Check for secret to confirm this is a valid request
if (req.query.secret !== process.env.MY_SECRET_TOKEN) {
return res.status(401).json({ message: 'Invalid token' })
}
try {
// This should be the actual path not a rewritten path
// e.g. for "/posts/[id]" this should be "/posts/1"
await res.revalidate('/posts/1')
return res.json({ revalidated: true })
} catch (err) {
// If there was an error, Next.js will continue
// to show the last successfully generated page
return res.status(500).send('Error revalidating')
}
}如果您正在使用按需重新驗證,則無需在 getStaticProps 中指定 revalidate 時間。Next.js 將使用預設值 false(不重新驗證),並且僅在呼叫 res.revalidate() 時按需重新驗證頁面。
處理未捕獲的異常
如果在處理後臺重新生成時 getStaticProps 內部出現錯誤,或者您手動丟擲錯誤,則上次成功生成的頁面將繼續顯示。在下一個後續請求中,Next.js 將重試呼叫 getStaticProps。
import type { GetStaticProps } from 'next'
interface Post {
id: string
title: string
content: string
}
interface Props {
post: Post
}
export const getStaticProps: GetStaticProps<Props> = async ({
params,
}: {
params: { id: string }
}) => {
// If this request throws an uncaught error, Next.js will
// not invalidate the currently shown page and
// retry getStaticProps on the next request.
const res = await fetch(`https://api.vercel.app/blog/${params.id}`)
const post: Post = await res.json()
if (!res.ok) {
// If there is a server error, you might want to
// throw an error instead of returning so that the cache is not updated
// until the next successful request.
throw new Error(`Failed to fetch posts, received status ${res.status}`)
}
return {
props: { post },
// Next.js will invalidate the cache when a
// request comes in, at most once every 60 seconds.
revalidate: 60,
}
}自定義快取位置
您可以配置 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 期間生成了哪些頁面,以及當按需訪問路徑時頁面是如何更新的。
注意事項
- ISR 僅在使用 Node.js 執行時(預設)時受支援。
- 建立靜態匯出時不支援 ISR。
- 代理不會為按需 ISR 請求執行,這意味著代理中的任何路徑重寫或邏輯都不會應用。請確保您重新驗證的是確切路徑。例如,
/post/1而不是重寫的/post-1。
平臺支援
| 部署選項 | 支援 |
|---|---|
| Node.js 伺服器 | 是 |
| Docker 容器 | 是 |
| 靜態匯出 | 否 |
| 介面卡 | 平臺特定 |
瞭解如何在自託管 Next.js 時配置 ISR。
版本歷史
| 版本 | 更改 |
|---|---|
v14.1.0 | 自定義 cacheHandler 已穩定。 |
v13.0.0 | App 路由器已引入。 |
v12.2.0 | Pages 路由器:按需 ISR 已穩定 |
v12.0.0 | Pages 路由器:添加了機器人感知 ISR 回退。 |
v9.5.0 | Pages 路由器:引入了穩定的 ISR。 |
這有幫助嗎?