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

Next.js同请求内fetch未缓存,如何实现请求复用?

解决Next.js中generateMetadata与组件内fetch请求重复调用的问题

你遇到的问题是在App Router的服务端组件中,generateMetadata和组件本身两次调用同一API却触发了两次请求,这和Next.js官方文档描述的请求缓存复用不符。下面是具体的原因分析和解决方法:

问题原因

虽然Next.js默认会在同一请求周期内对相同参数的fetch请求进行去重缓存,但以下情况可能导致缓存失效:

  • 请求的URL、headers、方法等参数存在细微差异(比如环境变量加载不一致)
  • 本地开发模式下的缓存策略与生产环境有差异
  • 未显式指定缓存策略,导致Next.js的自动去重未生效

解决方法:抽离逻辑并显式缓存

最可靠的方式是将获取文章的逻辑抽离为单独函数,并用Next.js提供的unstable_cache包裹,确保两次调用复用同一缓存结果。

修改后的完整代码

// posts/[slug]/page.tsx
import { Metadata } from "next";
import { unstable_cache } from 'next/cache';
import { PostResponse } from "@/service/model/api";

// 抽离获取文章的逻辑,并用unstable_cache缓存结果
const getPostBySlug = unstable_cache(
  async (slug: string) => {
    const response = await fetch(`${process.env.BASE_URL}/api/posts/slug?slug=${slug}`, {
      method: "GET",
      headers: {
        "Authorization": `Bearer ${process.env.API_KEY}`
      },
      cache: 'force-cache' // 显式指定强制缓存策略
    });

    if (!response.ok) {
      throw new Error(`Failed to fetch post: ${response.statusText}`);
    }

    const posts: PostResponse = await response.json();
    return posts.posts[0];
  },
  ['post-by-slug'], // 缓存键的唯一标识前缀
  { revalidate: 60 } // 可选:设置缓存自动刷新时间(单位:秒)
);

export async function generateMetadata(props: PostPageProps): Promise<Metadata> {
  const post = await getPostBySlug(props.params.slug);
  return {
    title: post.title
  };
}

export default async function PostPage(props: PostPageProps) {
  const post = await getPostBySlug(props.params.slug);
  return (
    <div>
      <p>{post.title}</p>
    </div>
  );
}

export interface PostPageProps {
  params: PostPageParams;
}

interface PostPageParams {
  slug: string;
  text?: string;
}

额外注意事项

  • 确保两次调用的请求参数完全一致:包括URL、headers、请求方法等,任何差异都会导致缓存不生效
  • 本地开发时若仍有问题,可以尝试重启开发服务器,确保环境变量加载一致
  • unstable_cache目前处于不稳定状态,但在App Router中是实现请求复用的可靠方式,后续Next.js可能会提供更稳定的API替代

内容的提问来源于stack exchange,提问作者Maxime Esnol

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 14:06:16