Next.js 13中generateMetadata与主组件同调API会触发两次请求吗?
问题解答
1. 当前代码会触发两次API请求吗?
是的,你写的这段代码会触发两次完全相同的API请求。因为generateMetadata和Page组件是两个独立执行的异步逻辑,二者内部的fetch调用没有共享数据,所以会各自向https://my-api.com/blog/${slug}发送一次请求。
2. 如何避免重复请求?
Next.js 13 App Router中无法直接通过props将Page组件获取的数据传递给generateMetadata——因为generateMetadata是在Page渲染前执行的,它的props仅包含路由相关的params、searchParams等信息,无法拿到Page里已获取的业务数据。要复用数据,推荐以下方案:
方案:提取公共数据获取函数 + 利用fetch自动缓存
把博客数据的获取逻辑抽成单独的异步函数,然后在generateMetadata和Page组件中分别调用。Next.js默认会对fetch的GET请求进行缓存,只要请求URL和参数完全一致,第二次调用会直接复用缓存结果,不会重复发送API请求。
修改后的代码示例:
// 提取公共数据获取函数 async function getBlog(slug: string) { const res = await fetch(`https://my-api.com/blog/${slug}`); // 可选:添加错误处理逻辑 if (!res.ok) { throw new Error('获取博客数据失败'); } return res.json(); } export async function generateMetadata({ params }: { params: { slug: string } }): Promise<Metadata> { const blog = await getBlog(params.slug); return { title: blog.title, description: blog.meta_description, keywords: blog.meta_keywords }; } export default async function Page({ params }: { params: { slug: string } }) { const blog = await getBlog(params.slug); return ( <div dangerouslySetInnerHTML={{ __html: blog?.content || '', }} /> ); }
缓存相关补充说明
- 默认情况下,
fetch会永久缓存请求结果(等价于配置cache: 'force-cache'),适合内容不频繁更新的博客场景。 - 如果需要实时获取最新数据(禁用缓存),可以在
fetch中添加配置:const res = await fetch(`https://my-api.com/blog/${slug}`, { cache: 'no-store' }); - 如果需要定期刷新缓存(比如每60秒更新一次内容),可以使用
next.revalidate配置:const res = await fetch(`https://my-api.com/blog/${slug}`, { next: { revalidate: 60 } });
内容的提问来源于stack exchange,提问作者Firmansyah
相关产品推荐
相关产品推荐

