Next.js 数据获取
规则
- 在服务器组件中使用 async/await 进行数据获取。不要使用
useEffect 处理初始数据。
- 在 App Router 中,
fetch() 默认是缓存的,除非指定 { cache: 'no-store' } 或 next: { revalidate }。请明确你所期望的行为。
- 使用
Promise.all 并行化独立请求,仅在依赖时按顺序执行。
- 将较慢的片段包裹在
<Suspense fallback> + loading.tsx 中以实现流式传输。
- 使用
next: { tags: ['posts'] } + revalidateTag('posts') 进行按需失效。
- 客户端数据获取(SWR/React Query)仅用于交互式/筛选型 UI——不用于首次渲染。
模式
async function getPosts() {
const res = await fetch('https://api.example.com/posts', {
next: { revalidate: 60 },
});
if (!res.ok) throw new Error('获取文章失败');
return res.json();
}
async function getInbox(userId: string) {
const res = await fetch(`https://api.example.com/inbox/${userId}`, {
cache: 'no-store',
});
return res.json();
}
export default async function Dashboard() {
const [user, posts] = await Promise.all([getUser(), getPosts()]);
return <View user={user} posts={posts} />;
}
import { Suspense } from 'react';
export default function Page() {
return (
<div>
<FastHeader />
<Suspense fallback={<CommentsSkeleton />}>
<SlowComments />
</Suspense>
</div>
);
}
import { revalidateTag } from 'next/cache';
export async function POST(req: Request) {
const { tag, secret } = await req.json();
if (secret !== process.env.REVALIDATE_SECRET)
return Response.json({ ok: false }, { status: 401 });
revalidateTag(tag);
return Response.json({ ok: true });
}
检查清单