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

Next.js App Router预渲染报错:因使用headers触发动态服务器错误

问题描述

在Next.js App Router项目中预渲染/pricing-plans页面时触发以下错误:

Error: Dynamic server usage: Page couldn't be rendered statically because it used `headers`. See more info here: https://nextjs.org/docs/messages/dynamic-server-error
    at o (D:\upwork\movein\new frontend\muuve-frontend\.next\server\app\(website)\pricing-plans\page.js:1:13234)
    at o (D:\upwork\movein\new frontend\muuve-frontend\.next\server\app\(website)\pricing-plans\page.js:1:12434)
Error occurred prerendering page "/pricing-plans". Read more: https://nextjs.org/docs/messages/prerender-error

注释掉getAgentPricingPlansAction调用后页面可正常运行。

代码片段

页面组件

import React from 'react';
import PricingPlansMain from '@/components/pages/PricingPlansPage';
import { getMeAction } from '@/server/auth-actions';
import { getAgentPricingPlansAction } from '@/server/payment-actions';
import PageLayout from '@/components/ui/PageLayout';
import UserCtxLayoutProvider from '@/components/ui/UserCtxLayoutProvider';
import styles from '@/components/pages/PricingPlansPage/styles.module.css';

export default async function PricingPlansPage() {
  const userData = (await getMeAction())?.success;
  const plans = await getAgentPricingPlansAction();

  return (
    <UserCtxLayoutProvider userData={userData}>
      <PageLayout
        headerClass={styles.header}
        headerTheme='light'
        logoConfig={{ theme: 'black', variant: 'full' }}
        headerVersion='full'
        footerTheme='default'
      >
        <PricingPlansMain plans={plans} />
      </PageLayout>
    </UserCtxLayoutProvider>
  );
}

操作函数

export const getMeAction = async () => {
  try {
    const res = await fetch(`${process.env.BACKEND_BASE}/users/me`, {
      cache: 'no-store',
      headers: { ...getAuthorizationHeader() },
      next: { tags: [getCacheKey('userData')] },
    });
    if (!res.ok) {
      throw new Error('server_error');
    }
    const { data } = await res.json();
    return { success: data as UserType };
  } catch (err) {
    return { error: 'server_error' };
  }
};

export async function getAgentPricingPlansAction() {
  try {
    const res: Response = await fetch(
      `${process.env.BACKEND_BASE}/payments/plans/prices`,
      {
        method: REQUEST_METHODS.GET,
        headers: {
          ...getNodeRequiredRequestHeaders(),
          ...getAuthorizationHeader(),
        },
      }
    );
    if (!res.ok) {
      throw new Error('unexpected error');
    }
    const data: PricingPlansActionResponseType = await res.json();
    return data;
  } catch (err: any) {
    throw new Error(err.message as string);
  }
}

原因分析

错误核心是:页面预渲染时尝试访问请求头(headers),但静态预渲染的页面无法获取动态请求上下文。getAgentPricingPlansAction中调用的getNodeRequiredRequestHeaders或getAuthorizationHeader函数,应该使用了Next.js的headers()方法——这个方法属于动态函数,仅能在动态渲染的页面/组件中使用。当Next.js尝试静态预渲染页面时,检测到这些动态函数调用,就会抛出该错误。

解决方案

1. 强制页面动态渲染

在页面组件文件顶部添加dynamic配置,告诉Next.js该页面必须动态渲染,不再尝试静态预渲染:

export const dynamic = 'force-dynamic'; // 添加该行代码

export default async function PricingPlansPage() {
  // ... 原有代码
}

这种方式简单直接,适合需要根据用户请求头(如授权信息)返回不同内容的页面。

2. 分离静态与动态逻辑(可选)

如果定价计划内容本身是静态的,不需要用户授权信息,可以修改getAgentPricingPlansAction,移除依赖headers()的请求头,或仅在有用户授权时才添加这些头:

export async function getAgentPricingPlansAction() {
  const headers: HeadersInit = { ...getNodeRequiredRequestHeaders() };
  // 仅在存在授权信息时添加头(需确保getAuthorizationHeader不会强制调用headers())
  const authHeader = getAuthorizationHeader();
  if (authHeader) {
    Object.assign(headers, authHeader);
  }

  try {
    const res: Response = await fetch(
      `${process.env.BACKEND_BASE}/payments/plans/prices`,
      {
        method: REQUEST_METHODS.GET,
        headers,
        next: { revalidate: 86400 } // 静态内容可添加长期缓存策略
      }
    );
    if (!res.ok) {
      throw new Error('unexpected error');
    }
    const data: PricingPlansActionResponseType = await res.json();
    return data;
  } catch (err: any) {
    throw new Error(err.message as string);
  }
}

这种方式允许页面在无用户授权时静态预渲染,有用户时动态渲染,但需要后端接口支持无授权访问定价计划。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 05:05:02