Skip to content

缓存和重新验证

¥Caching and Revalidating

缓存是一种存储数据获取和其他计算结果的技术,以便将来对相同数据的请求能够更快地得到处理,而无需重复工作。重新验证允许你更新缓存条目,而无需重建整个应用。

¥Caching is a technique for storing the result of data fetching and other computations so that future requests for the same data can be served faster, without doing the work again. While revalidation allows you to update cache entries without having to rebuild your entire application.

Next.js 提供了一些 API 来处理缓存和重新验证。本指南将引导你了解何时以及如何使用它们。

¥Next.js provides a few APIs to handle caching and revalidation. This guide will walk you through when and how to use them.

fetch

默认情况下,fetch 请求不会被缓存。你可以通过将 cache 选项设置为 'force-cache' 来缓存单个请求。

¥By default, fetch requests are not cached. You can cache individual requests by setting the cache option to 'force-cache'.

tsx
export default async function Page() {
  const data = await fetch('https://...', { cache: 'force-cache' })
}

需要了解:虽然默认情况下不缓存 fetch 请求,但 Next.js 会对包含 fetch 请求的路由进行 pre-render 处理,并缓存 HTML。如果你想保证路由是 dynamic,请使用 connection API

¥Good to know: Although fetch requests are not cached by default, Next.js will pre-render routes that have fetch requests and cache the HTML. If you want to guarantee a route is dynamic, use the connection API.

为重新验证 fetch 请求返回的数据,你可以使用 next.revalidate 选项。

¥To revalidate the data returned by a fetch request, you can use the next.revalidate option.

tsx
export default async function Page() {
  const data = await fetch('https://...', { next: { revalidate: 3600 } })
}

这将在指定的秒数后重新验证数据。

¥This will revalidate the data after a specified amount of seconds.

你还可以标记 fetch 请求以启用按需缓存失效:

¥You can also tag fetch requests to enable on-demand cache invalidation:

tsx
export async function getUserById(id: string) {
  const data = await fetch(`https://...`, {
    next: {
      tags: ['user'],
    },
  })
}

有关更多信息,请参阅 fetch API 参考

¥See the fetch API reference to learn more.

cacheTag

cacheTag 允许你在 缓存组件 中标记缓存数据,以便按需重新验证。以前,缓存标记仅限于 fetch 请求,缓存其他工作需要使用实验性的 unstable_cache API。

¥cacheTag allows you to tag cached data in Cache Components so it can be revalidated on-demand. Previously, cache tagging was limited to fetch requests, and caching other work required the experimental unstable_cache API.

使用缓存组件,你可以使用 use cache 指令缓存任何计算,并使用 cacheTag 指令对其进行标记。这适用于数据库查询、文件系统操作和其他服务器端工作。

¥With Cache Components, you can use the use cache directive to cache any computation, and cacheTag to tag it. This works with database queries, file system operations, and other server-side work.

tsx
import { cacheTag } from 'next/cache'

export async function getProducts() {
  'use cache'
  cacheTag('products')

  const products = await db.query('SELECT * FROM products')
  return products
}

标记后,你可以使用 revalidateTagupdateTag 来使产品的缓存条目失效。

¥Once tagged, you can use revalidateTag or updateTag to invalidate the cache entry for products.

需要了解:cacheTag缓存组件use cache 指令一起使用。它将缓存和重新验证机制扩展到 fetch 之外。

¥Good to know: cacheTag is used with Cache Components and the use cache directive. It expands the caching and revalidation story beyond fetch.

有关更多信息,请参阅 cacheTag API 参考

¥See the cacheTag API reference to learn more.

revalidateTag

revalidateTag 用于根据标签和事件重新验证缓存条目。该函数现在支持两种行为:

¥revalidateTag is used to revalidate cache entries based on a tag and following an event. The function now supports two behaviors:

  • 使用 profile="max":使用“重新验证时提供过时内容”语义,在后台获取新内容的同时提供过时的内容。

    ¥With profile="max": Uses stale-while-revalidate semantics, serving stale content while fetching fresh content in the background

  • 不使用第二个参数:立即使缓存过期的旧版行为(已弃用)

    ¥Without the second argument: Legacy behavior that immediately expires the cache (deprecated)

使用 fetchnext.tagscacheTag 函数标记缓存数据后,你可以在 路由处理程序 或服务器操作中调用 revalidateTag

¥After tagging your cached data, using fetch with next.tags, or the cacheTag function, you may call revalidateTag in a Route Handler or Server Action:

tsx
import { revalidateTag } from 'next/cache'

export async function updateUser(id: string) {
  // Mutate data
  revalidateTag('user', 'max') // Recommended: Uses stale-while-revalidate
}

你可以在多个函数中重复使用同一个标签,以便一次性重新验证所有函数。

¥You can reuse the same tag in multiple functions to revalidate them all at once.

有关更多信息,请参阅 revalidateTag API 参考

¥See the revalidateTag API reference to learn more.

updateTag

updateTag 专门用于服务器操作,以便在读写场景中立即使缓存数据过期。与 revalidateTag 不同,它只能在服务器操作中使用,并且会立即使缓存条目过期。

¥updateTag is specifically designed for Server Actions to immediately expire cached data for read-your-own-writes scenarios. Unlike revalidateTag, it can only be used within Server Actions and immediately expires the cache entry.

tsx
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}`)
}

revalidateTagupdateTag 的主要区别:

¥The key differences between revalidateTag and updateTag:

  • updateTag:仅在服务器操作中,立即过期缓存,用于读写操作

    ¥updateTag: Only in Server Actions, immediately expires cache, for read-your-own-writes

  • revalidateTag:在服务器操作和路由处理程序中,支持使用 profile="max" 实现 stale-while-revalidate 功能。

    ¥revalidateTag: In Server Actions and Route Handlers, supports stale-while-revalidate with profile="max"

有关更多信息,请参阅 updateTag API 参考

¥See the updateTag API reference to learn more.

revalidatePath

revalidatePath 用于重新验证路由和事件。要使用它,请在 路由处理程序 或服务器操作中调用它:

¥revalidatePath is used to revalidate a route and following an event. To use it, call it in a Route Handler or Server Action:

tsx
import { revalidatePath } from 'next/cache'

export async function updateUser(id: string) {
  // Mutate data
  revalidatePath('/profile')

有关更多信息,请参阅 revalidatePath API 参考

¥See the revalidatePath API reference to learn more.

unstable_cache

需要了解:unstable_cache 是一个实验性 API。我们建议启用 缓存组件 并将 unstable_cache 替换为 use cache 指令。有关详细信息,请参阅 缓存组件文档

¥Good to know: unstable_cache is an experimental API. We recommend opting into Cache Components and replacing unstable_cache with the use cache directive. See the Cache Components documentation for more details.

unstable_cache 允许你缓存数据库查询和其他异步函数的结果。要使用它,请将 unstable_cache 封装在该函数周围。例如:

¥unstable_cache allows you to cache the result of database queries and other async functions. To use it, wrap unstable_cache around the function. For example:

ts
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])
}
tsx
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
  )
}

该函数接受第三个可选对象来定义如何重新验证缓存。它接受:

¥The function accepts a third optional object to define how the cache should be revalidated. It accepts:

  • tags:Next.js 用于重新验证缓存的标签数组。

    ¥tags: an array of tags used by Next.js to revalidate the cache.

  • revalidate:缓存重新验证后的秒数。

    ¥revalidate: the number of seconds after cache should be revalidated.

tsx
const getCachedUser = unstable_cache(
  async () => {
    return getUserById(userId)
  },
  [userId],
  {
    tags: ['user'],
    revalidate: 3600,
  }
)

有关更多信息,请参阅 unstable_cache API 参考

¥See the unstable_cache API reference to learn more.