缓存和重新验证
缓存是一种存储数据获取和其他计算结果的技术,以便将来对相同数据的请求可以更快地提供服务,而无需再次执行工作。而重新验证允许你更新缓存条目,而无需重建整个应用程序。
Next.js 提供了几个 API 来处理缓存和重新验证。本指南将指导你何时以及如何使用它们。
fetch
默认情况下,fetch 请求不会被缓存。你可以通过将 cache 选项设置为 'force-cache' 来缓存单个请求。
- TypeScript
 - JavaScript
 
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 选项。
- TypeScript
 - JavaScript
 
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 API 参考了解更多信息。
unstable_cache
unstable_cache 允许你缓存数据库查询和其他异步函数的结果。要使用它,请用 unstable_cache 包装函数。例如:
- TypeScript
 - JavaScript
 
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])
}
- TypeScript
 - JavaScript
 
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] // 将用户 ID 添加到缓存键
  )
}
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] // 将用户 ID 添加到缓存键
  );
}
该函数接受第三个可选对象来定义应如何重新验证缓存。它接受:
tags:Next.js 用于重新验证缓存的标签数组。revalidate:缓存应重新验证的秒数。
- TypeScript
 - JavaScript
 
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 参考了解更多信息。
revalidateTag
revalidateTag 用于基于标签和事件重新验证缓存条目。要与 fetch 一起使用,首先用 next.tags 选项标记函数:
- TypeScript
 - JavaScript
 
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'],
    },
  })
}
或者,你可以用 tags 选项标记 unstable_cache 函数:
- TypeScript
 - JavaScript
 
export const getUserById = unstable_cache(
  async (id: string) => {
    return db.query.users.findFirst({ where: eq(users.id, id) })
  },
  ['user'], // 如果变量不作为参数传递则需要
  {
    tags: ['user'],
  }
)
export const getUserById = unstable_cache(
  async (id) => {
    return db.query.users.findFirst({ where: eq(users.id, id) })
  },
  ['user'], // 如果变量不作为参数传递则需要
  {
    tags: ['user'],
  }
)
然后,在路由处理器或服务端操作中调用 revalidateTag:
- TypeScript
 - JavaScript
 
import { revalidateTag } from 'next/cache'
export async function updateUser(id: string) {
  // 修改数据
  revalidateTag('user')
}
import { revalidateTag } from 'next/cache'
export async function updateUser(id) {
  // 修改数据
  revalidateTag('user')
}
你可以在多个函数中重用相同的标签来一次性重新验证它们。
请参阅 revalidateTag API 参考了解更多信息。
revalidatePath
revalidatePath 用于重新验证路由和事件。要使用它,在路由处理器或服务端操作中 调用它:
- TypeScript
 - JavaScript
 
import { revalidatePath } from 'next/cache'
export async function updateUser(id: string) {
  // 修改数据
  revalidatePath('/profile')
import { revalidatePath } from 'next/cache'
export async function updateUser(id) {
  // 修改数据
  revalidatePath('/profile')
请参阅 revalidatePath API 参考了解更多信息。