缓存是一种存储数据获取和其他计算结果的技术,这样一来,未来对相同数据的请求可以更快地得到响应,而无需再次执行相同的工作。同时,重新验证允许您更新缓存条目,而无需重建整个应用程序。
Next.js 提供了一些 API 来处理缓存和重新验证。本指南将引导您了解何时以及如何使用它们。
fetch默认情况下,fetch 请求不会被缓存。您可以通过将 cache 选项设置为 'force-cache' 来缓存单个请求。
export default async function Page() {
const data = await fetch('https://...', { cache: 'force-cache' })
}export default async function Page() {
const data = await fetch('https://...', { cache: 'force-cache' })
}须知: 尽管
fetch请求默认不被缓存,Next.js 会 预渲染 包含fetch请求的路由并缓存 HTML。如果您想确保路由是 动态的,请使用connectionAPI。
要重新验证 fetch 请求返回的数据,您可以使用 next.revalidate 选项。
export default async function Page() {
const data = await fetch('https://...', { next: { revalidate: 3600 } })
}export default async function Page() {
const data = await fetch('https://...', { next: { revalidate: 3600 } })
}这将在指定的秒数后重新验证数据。
您还可以标记 fetch 请求以启用按需缓存失效:
export async function getUserById(id: string) {
const data = await fetch(`https://...`, {
next: {
tags: ['user'],
},
})
}export async function getUserById(id) {
const data = await fetch(`https://...`, {
next: {
tags: ['user'],
},
})
}请参阅 fetch API 参考 了解更多信息。
cacheTagcacheTag 允许您在 缓存组件 中标记已缓存的数据,以便按需重新验证。以前,缓存标记仅限于 fetch 请求,缓存其他工作则需要实验性的 unstable_cache API。
通过缓存组件,您可以使用 use cache 指令来缓存任何计算,并使用 cacheTag 进行标记。这适用于数据库查询、文件系统操作以及其他服务器端工作。
import { cacheTag } from 'next/cache'
export async function getProducts() {
'use cache'
cacheTag('products')
const products = await db.query('SELECT * FROM products')
return products
}import { cacheTag } from 'next/cache'
export async function getProducts() {
'use cache'
cacheTag('products')
const products = await db.query('SELECT * FROM products')
return products
}一旦被标记,您就可以使用 revalidateTag 或 updateTag 来使产品的缓存条目失效。
须知:
cacheTag与 缓存组件 和use cache指令配合使用。它扩展了fetch之外的缓存和重新验证功能。
请参阅 cacheTag API 参考 了解更多信息。
revalidateTagrevalidateTag 用于根据标签和发生事件后重新验证缓存条目。该函数现在支持两种行为:
profile="max": 采用陈旧时重新验证的语义,即在后台获取新内容的同时提供旧内容。在使用 fetch 的 next.tags 或 cacheTag 函数标记您的缓存数据后,您可以在 路由处理程序 或 服务器动作 中调用 revalidateTag:
import { revalidateTag } from 'next/cache'
export async function updateUser(id: string) {
// Mutate data
revalidateTag('user', 'max') // Recommended: Uses stale-while-revalidate
}import { revalidateTag } from 'next/cache'
export async function updateUser(id) {
// Mutate data
revalidateTag('user', 'max') // Recommended: Uses stale-while-revalidate
}您可以在多个函数中重复使用相同的标签,以同时重新验证所有这些函数。
请参阅 revalidateTag API 参考 了解更多信息。
updateTagupdateTag 专门为服务器动作设计,用于在读写一致性场景中立即使缓存数据失效。与 revalidateTag 不同,它只能在服务器动作中使用,并立即使缓存条目过期。
import { updateTag } from 'next/cache'
import { redirect } from 'next/navigation'
export async function createPost(formData: FormData) {
// Create post in database
const post = await db.post.create({
data: {
title: formData.get('title'),
content: formData.get('content'),
},
})
// Immediately expire cache so the new post is visible
updateTag('posts')
updateTag(`post-${post.id}`)
redirect(`/posts/${post.id}`)
}import { updateTag } from 'next/cache'
import { redirect } from 'next/navigation'
export async function createPost(formData) {
// Create post in database
const post = await db.post.create({
data: {
title: formData.get('title'),
content: formData.get('content'),
},
})
// Immediately expire cache so the new post is visible
updateTag('posts')
updateTag(`post-${post.id}`)
redirect(`/posts/${post.id}`)
}revalidateTag 和 updateTag 之间的主要区别:
updateTag: 仅在服务器动作中使用,立即使缓存过期,用于读写一致性。revalidateTag: 在服务器动作和路由处理程序中使用,支持 profile="max" 的陈旧时重新验证。请参阅 updateTag API 参考 了解更多信息。
revalidatePathrevalidatePath 用于重新验证路由和发生事件后。要使用它,请在 路由处理程序 或 服务器动作 中调用它:
import { revalidatePath } from 'next/cache'
export async function updateUser(id: string) {
// Mutate data
revalidatePath('/profile')import { revalidatePath } from 'next/cache'
export async function updateUser(id) {
// Mutate data
revalidatePath('/profile')请参阅 revalidatePath API 参考 了解更多信息。
unstable_cache须知:
unstable_cache是一个实验性 API。我们建议采用 缓存组件 并使用use cache指令替换unstable_cache。有关更多详细信息,请参阅 缓存组件文档。
unstable_cache 允许您缓存数据库查询和其他异步函数的结果。要使用它,请将 unstable_cache 包装在函数周围。例如:
import { db } from '@/lib/db'
export async function getUserById(id: string) {
return db
.select()
.from(users)
.where(eq(users.id, id))
.then((res) => res[0])
}import { db } from '@/lib/db'
export async function getUserById(id) {
return db
.select()
.from(users)
.where(eq(users.id, id))
.then((res) => res[0])
}import { unstable_cache } from 'next/cache'
import { getUserById } from '@/app/lib/data'
export default async function Page({
params,
}: {
params: Promise<{ userId: string }>
}) {
const { userId } = await params
const getCachedUser = unstable_cache(
async () => {
return getUserById(userId)
},
[userId] // add the user ID to the cache key
)
}import { unstable_cache } from 'next/cache'
import { getUserById } from '@/app/lib/data'
export default async function Page({ params }) {
const { userId } = await params
const getCachedUser = unstable_cache(
async () => {
return getUserById(userId)
},
[userId] // add the user ID to the cache key
)
}该函数接受第三个可选对象来定义缓存应如何重新验证。它接受:
tags: Next.js 用于重新验证缓存的标签数组。revalidate: 缓存应重新验证的秒数。const getCachedUser = unstable_cache(
async () => {
return getUserById(userId)
},
[userId],
{
tags: ['user'],
revalidate: 3600,
}
)const getCachedUser = unstable_cache(
async () => {
return getUserById(userId)
},
[userId],
{
tags: ['user'],
revalidate: 3600,
}
)请参阅 unstable_cache API 参考 了解更多信息。