数据获取
数据获取、缓存和重新验证
数据获取是任何应用程序的核心部分。
本页介绍了在React和Next.js中如何获取、缓存和重新验证数据。
有四种获取数据的方式:
- 在服务器上使用
fetch
- 在服务器上使用第三方库
- 通过路由处理程序在客户端上获取
- 在客户端上使用第三方库。
使用fetch在服务器上获取数据
Next.js扩展了原生的[fetch Web API,
允许您在服务器上为每个fetch
请求配置
缓存和重新验证行为。
React通过在呈现React组件树时自动
记忆fetch
请求来扩展fetch
。
您可以在Server Components、
Route Handlers
和Server Actions
中使用带有async/await
的fetch
。
async function getData() {
const res = await fetch('https://api.example.com/...')
// 返回值未序列化
// 可以返回Date、Map、Set等。
if (!res.ok) {
// 这将激活最接近的`error.js`错误边界
throw new Error('获取数据失败')
}
return res.json()
}
export default async function Page() {
const data = await getData()
return <main></main>
}
- Next.js提供了在Server Components中获取数据时可能需要的有用函数,如
cookies
和headers
。 由于它们依赖于请求时间信息,它们将导致路由动态渲染。 - 在Route Handlers中,
fetch
请求不会被记忆,因为Route Handlers不是React组件树的一部分。 - 要在带有TypeScript的Server Component中使用
async/await
, 您需要使用TypeScript5.1.3
或更高版本和@types/react
18.2.8
或更高版本。
缓存数据
缓存会存储数据,使得不必在每个请求上都重新从数据源获取数据。
默认情况下,Next.js会自动将fetch
返回的值缓存到服务器上的
Data Cache中。
这意味着数据可以在构建时间或请求时间获取,被缓存,并在每次数据请求时重复使用。
// 'force-cache'是默认值,可以省略
fetch('https://...', { cache: 'force-cache' })
使用POST
方法的fetch
请求也会自动缓存。
除非它在使用POST
方法的
Route Handler
中,否则它将不会被缓存。
什么是Data Cache?
Data Cache是一个持久性 HTTP缓存。 根据您的平台,缓存可以自动扩展并在 多个 地区共享。 了解有关Data Cache的更多信息。
重新验证数据
重新验证是清除Data Cache并重新获取最新数据的过程。 当数据发生变化并且您希望确保显示最新信息时,这很有用。
缓存的数据可以通过两种方式重新验证:
- 基于时间的重新验证:在经过一定时间后自动重新验证数据。这对于数据变化不频繁且新鲜度不是很关键的数据很有用。
- 按需重新验证:根据事件(例如表单提交)手动重新验证数据。按需重新验证可以使用基于标签或基于路径的方法一次重新验证多个数据组。当您希望尽快显示最新数据时很有用(例如,当来自您的无头CMS的内容已更新时)。
基于时间的重新验证
要在定时间隔内重新验证数据,可以使用fetch
的next.revalidate
选项设置资源的缓存生存时间(以秒为单位)。
fetch('https://...', { next: { revalidate: 3600 } })
或者,要重新验证路由段中的所有fetch
请求,可以使用
Segment Config Options。
export const revalidate = 3600 // 最多每小时重新验证一次
如果在静态渲染的路由中有多个fetch
请求,
且每个请求具有不同的重新验证频率,
则将使用最低时间来重新验证所有请求。
对于动态渲染的路由,每个fetch
请求将独立重新验证。
了解有关基于时间的重新验证的更多信息。
按需重新验证
可以通过路径(revalidatePath
)或缓存标签(revalidateTag
)在
Server Action或
Route Handler
中重新验证数据。
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
标签的此fetch
调用:
'use server'
import { revalidateTag } from 'next/cache'
export default async function action() {
revalidateTag('collection')
}
了解有关按需重新验证的更多信息。
错误处理和重新验证
如果在尝试重新验证数据时抛出错误,将继续从缓存中提供上次成功生成的数据。 在下一次请求时,Next.js将重试重新验证数据。
退出数据缓存
如果存在以下情况,则不会对fetch
请求进行缓存:
- 将
cache: 'no-store'
添加到fetch
请求中。 - 将
revalidate: 0
选项添加到个别fetch
请求。 fetch
请求在使用POST
方法的Router Handler中。fetch
请求在headers
或cookies
的使用之后。- 使用
const dynamic = 'force-dynamic'
路由段选项。 - 通过配置
fetchCache
路由段选项跳过缓存,默认情况下不会缓存。 fetch
请求使用Authorization
或Cookie
头,并且在组件树中有未缓存的请求。
个别fetch请求
要禁用个别fetch
请求的缓存,可以在fetch
的选项中
将cache选项设置为'no-store'
。这将在每个请求上动态获取数据。
fetch('https://...', { cache: 'no-store' })
在fetch
API参考
中查看所有可用的缓存选项。
多个fetch请求
如果在一个路由段(例如Layout
或Page
)中有多个fetch
请求,
可以使用
Segment Config Options
配置段中所有数据请求的缓存行为。
但是,我们建议单独配置每个fetch
请求的缓存行为。这样可以更精细地控制缓存行为。