获取, 缓存和重新验证
Data Fetching(数据获取) 是应用程序的核心部分. 本页面将会带你了解在 Next.js 和 React 中获取数据, 缓存数据和重新验证数据.
你可以使用四种方法来获取数据:
Fetching Data on the Server with fetch
(通过 fetch
在服务器端获取数据)
Next.js 扩展了原生的 fetch
Web API, 允许你为服务器端上的每个 fetch
请求配置cache(缓存)和revalidating(重新验证)行为. React 对 fetch
进行了扩展, 以便在渲染 React 组件树时自动memoize(记忆) fetch 请求.
你可以在 Server Component(服务端组件)/Route Handlers(路由处理器)/Server Actions(服务端行为)中通过 async/await
来使用 fetch
.
比如:
async function getData() {
const res = await fetch("https://api.example.com/...");
// The return value is *not* serialized
// You can return Date, Map, Set, etc.
if (!res.ok) {
// This will activate the closest `error.js` Error Boundary
throw new Error("Failed to fetch data");
}
return res.json();
}
export default async function Page() {
const data = await getData();
return <main></main>;
}
请注意:
- Next.js 在 Server Components(服务端组件)中为你提供了一些获取数据时有用的函数, 比如 cookie 和 headers. 这会导致该路由 变为动态渲染(因为它们依赖于请求时间信息).
- 在 Route Handlers(路由处理器)中,
fetch
请求不会被自动记忆, 因为 Route Handlers(路由处理器) 不是 React 组件树的一部分.- 为了在 Server Components(服务端组件) 中通过 Typescript 使用
async/await
, 你需要 Typescript5.1.3
版本或更高版本,@types/react
18.2.8
或更高版本.
Caching Data (缓存数据)
缓存获取的数据, 这样每次请求时就无需从数据源重新获取数据.
默认情况下, Next.js 会自动将 fetch
的返回值缓存到服务器上的Data Cache(数据缓存)中. 这意味着数据会在构建时或请求时获取并缓存, 并在该数据重新请求时重复使用.
// 'force-cache' is the default, and can be omitted
fetch("https://...", { cache: "force-cache" });
使用 POST
方法的 fetch
请求也会被自动缓存. 在 Route Handlers(路由处理器) 中在使用 POST
方法是不会被缓存的.
什么是 Data Cache(数据缓存)?
数据缓存是一种持久化的 HTTP 缓存. 根据平台的不同,缓存可自动扩展并在多个区域共享.
了解有关数据缓存的更多信息.
Revalidating Data (数据重新验证)
数据重新验证是清理 Data Cache(数据缓存) 并重新获取最新数据的过程. 当您的数据发生变化, 并希望确保显示最新信息时, 这种方法非常有用.
缓存的数据会在下面两种方式下被重新验证:
- Time-based revalidation(基于时间的重新验证): 在一定时间后自动重新验证数据. 这对于变化不频繁, 实时性要求不高的数据非常有用.
- On-demand revalidation(基于需求的重新验证): 基于事件(像表单提交), 手动重新验证数据. 按需重新验证可以使用基于标签或路径的方法来一次性重新验证一组数据. 当你想确保尽快显示最新数据时(例如, 当无 head 内容管理系统的内容更新时), 这种方法非常有用.
Time-based Revalidation (基于时间的重新验证)
为了间隔性的重新验证数据, 你可以在 fetch
中使用 next.revalidate
选项来设置缓存资源的生命周期(通过秒数设置).
fetch("https://...", { next: { revalidate: 3600 } });
另外, 如果要在一个路由段中重新验证所有的 fetch
请求, 你可以使用 Segment Config Options(段配置选项).
export const revalidate = 3600; // revalidate at most every hour
如果在一个静态渲染的路由中有多个 fetch
请求, 且每个请求的重新验证频率不同. 所有请求都将使用最低时间. 对于动态渲染的路由, 每个 fetch
请求都将独立重新验证.
了解更多关于 time-based revalidation(基于时间的重新验证).
On-demand Revalidation (基于需求的重新验证)
数据可根据路径( revalidatePath
) 或 Server Action(服务器行为) / Route Handler(路由处理器)的缓存标签(revalidateTag
)来按需求重新验证.
Next.js 有一个缓存标记系统, 用于使跨路由的 fetch
请求无效.
- 当使用
fetch
时, 你使用一个或多个标记来标记缓存条目. - 然后, 你可以调用
revalidateTag
来重新获取该标记下的所有缓存条目.
比如, 在下面的 fetch
请求中增加 collection
缓存标记:
export default async function Page() {
const res = await fetch("https://...", { next: { tags: ["collection"] } });
const data = await res.json();
// ...
}
然后, 你可以通过 Server Action(服务器行为) 中调用 revalidateTag
来重新验证这个带有 collection
标记的获取调用:
"use server";
import { revalidateTag } from "next/cache";
export default async function action() {
revalidateTag("collection");
}
了解更多关于 on-demand revalidation(基于需求的重新验证).