数据获取和缓存
¥Data Fetching and Caching
本指南将引导你了解 Next.js 中数据提取和缓存的基础知识,并提供实际示例和最佳实践。
¥This guide will walk you through the basics of data fetching and caching in Next.js, providing practical examples and best practices.
以下是 Next.js 中数据提取的一个最小示例:
¥Here's a minimal example of data fetching in Next.js:
export default async function Page() {
const data = await fetch('https://api.vercel.app/blog')
const posts = await data.json()
return (
<ul>
{posts.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
)
}
此示例演示了在异步 React 服务器组件中使用 fetch
API 进行基本的服务器端数据提取。
¥This example demonstrates a basic server-side data fetch using the fetch
API in an asynchronous React Server Component.
参考
¥Reference
React
cache
Next.js
unstable_cache
使用 ORM 或数据库缓存数据
¥Caching data with an ORM or Database
你可以在运行 next build
时使用 unstable_cache
API 缓存响应。
¥You can use the unstable_cache
API to cache the response when running next build
.
import { unstable_cache } from 'next/cache'
import { db, posts } from '@/lib/db'
const getPosts = unstable_cache(
async () => {
return await db.select().from(posts)
},
['posts'],
{ revalidate: 3600, tags: ['posts'] }
)
export default async function Page() {
const allPosts = await getPosts()
return (
<ul>
{allPosts.map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
)
}
此示例将数据库查询的结果缓存 1 小时(3600 秒)。它还添加了缓存标签 posts
,然后可以使用 增量静态再生 使其无效。
¥This example caches the result of the database query for 1 hour (3600 seconds). It also adds the cache tag posts
which can then be invalidated with Incremental Static Regeneration.
在多个函数中重用数据
¥Reusing data across multiple functions
Next.js 使用 generateMetadata
和 generateStaticParams
等 API,你需要使用在 page
中获取的相同数据。
¥Next.js uses APIs like generateMetadata
and generateStaticParams
where you will need to use the same data fetched in the page
.
如果你正在使用 fetch
,则可以通过添加 cache: 'force-cache'
将请求变为 memoized。这意味着你可以安全地使用相同的选项调用相同的 URL,并且只会发出一个请求。
¥If you are using fetch
, requests can be memoized by adding cache: 'force-cache'
. This means you can safely call the same URL with the same options, and only one request will be made.
需要了解:
¥Good to know:
在以前版本的 Next.js 中,使用
fetch
的默认cache
值为force-cache
。这在版本 15 中更改为默认值cache: no-store
。¥In previous versions of Next.js, using
fetch
would have a defaultcache
value offorce-cache
. This changed in version 15, to a default ofcache: no-store
.
import { notFound } from 'next/navigation'
interface Post {
id: string
title: string
content: string
}
async function getPost(id: string) {
const res = await fetch(`https://api.vercel.app/blog/${id}`, {
cache: 'force-cache',
})
const post: Post = await res.json()
if (!post) notFound()
return post
}
export async function generateStaticParams() {
const posts = await fetch('https://api.vercel.app/blog', {
cache: 'force-cache',
}).then((res) => res.json())
return posts.map((post: Post) => ({
id: String(post.id),
}))
}
export async function generateMetadata({
params,
}: {
params: Promise<{ id: string }>
}) {
const { id } = await params
const post = await getPost(id)
return {
title: post.title,
}
}
export default async function Page({
params,
}: {
params: Promise<{ id: string }>
}) {
const { id } = await params
const post = await getPost(id)
return (
<article>
<h1>{post.title}</h1>
<p>{post.content}</p>
</article>
)
}
如果你不使用 fetch
,而是直接使用 ORM 或数据库,则可以使用 React cache
函数封装数据获取。这将删除重复项并仅进行一次查询。
¥If you are not using fetch
, and instead using an ORM or database directly, you can wrap your data fetch with the React cache
function. This will de-duplicate and only make one query.
重新验证缓存数据
¥Revalidating cached data
了解有关使用 增量静态再生 重新验证缓存数据的更多信息。
¥Learn more about revalidating cached data with Incremental Static Regeneration.