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

App Router下动态页面为何在构建阶段发起请求?

为什么Next.js动态页面在构建阶段也会执行数据请求,且多次触发?

构建阶段触发两次请求的原因

  1. 元数据预渲染逻辑:你在generateMetadata里调用了getData,Next.js为了提前生成SEO所需的页面元数据(标题、描述),会在构建阶段执行这个函数。哪怕页面是动态的,只要元数据不依赖cookies、请求参数这类动态上下文,Next.js就会尝试在构建时预生成它,这是第一次数据请求的来源。
  2. 动态页面的预渲染尝试:你的页面因为使用了cookies(),被标记为「按需SSR」的动态页面,但Next.js在构建时仍会尝试预渲染页面一次,验证是否能生成静态内容。由于构建环境中没有access-token这个cookie,代码会走到const data = await getData()这一步,触发第二次数据请求。

用户访问时再次触发请求的原因

当用户访问页面时,因为页面依赖动态上下文(cookies),Next.js会在服务器端重新渲染整个页面:

  • 首先调用generateMetadata生成当前请求对应的元数据(动态页面的元数据不会复用构建时的结果,会在每次请求时重新生成);
  • 然后渲染Page组件,再次调用getData。
    所以每次用户访问都会触发两次数据请求。

解决方法

1. 同一请求内复用数据,避免重复请求

用React.cache包裹getData,让同一个请求内的多次调用共享同一份数据结果,减少实际发起的网络请求:

import { cache } from 'react';

const getData = cache(async () => {
  try {
    const res = await getDataWithAxios<MockoonResponse>({
      method: "get",
      params: {
        whatever: "123",
      },
      endpoint: "http://127.0.0.1:4003/api/mockoontest",
    });
    return res;
  } catch (error) {
    console.error(error);
  }
});

2. 阻止构建阶段的元数据预生成

如果不需要在构建阶段生成元数据,可以让generateMetadata依赖动态上下文,比如读取cookies,让Next.js知道这是动态元数据,不会在构建时预生成:

export async function generateMetadata() {
  // 读取cookies,标记元数据为动态
  cookies();
  const res = await getData();
  return {
    title: res?.seo.title,
    description: res?.seo.description,
  };
}

3. 禁用页面的构建预渲染尝试

添加export const dynamic = 'force-dynamic',明确标记页面为完全动态,Next.js就不会在构建时尝试预渲染页面,彻底避免构建阶段的页面侧数据请求:

export const dynamic = 'force-dynamic';

// 其余代码不变

内容的提问来源于stack exchange,提问作者Professor Chaos

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 23:53:17