You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 23:55:14