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

Next.js App Router预渲染报错:Vercel部署时API请求失败

问题:Next.js App Router部署Vercel时预渲染页面报错

开发环境运行正常,但部署到Vercel时触发Error occurred prerendering page "/",排查确认是Featured组件的getData方法请求/api/products接口失败——核心原因是构建阶段项目的API路由还未启动服务,无法通过HTTP请求访问。


解决方案

方案1:直接调用API路由的逻辑代码(推荐)

跳过HTTP请求,直接导入API路由里的业务逻辑函数。因为构建阶段同项目的API路由未启动,但代码文件可以正常访问。

假设你的API路由逻辑在app/api/products/route.ts中,并且导出了获取产品的函数(比如getProducts),修改getData方法如下:

// 导入API路由的逻辑函数
import { getProducts } from '@/app/api/products/route';

const getData = async () => {
  // 直接调用逻辑函数,无需发起HTTP请求
  const data = await getProducts();
  const validatedProducts = productArraySchema.parse(data);
  return validatedProducts;
};

方案2:强制动态渲染跳过预渲染

如果必须保留HTTP请求逻辑,可以让组件或页面跳过预渲染,改为动态渲染:

  • 方法A:在page.tsx中动态导入组件并禁用SSR
import dynamic from 'next/dynamic';

// 动态导入Featured组件,强制客户端渲染
const Featured = dynamic(() => import('./path-to-featured-component'), {
  ssr: false,
});

const Home = () => {
  // 原页面代码不变
};

export default Home;
  • 方法B:在Featured组件顶部添加动态渲染指令
// 在Featured组件最顶部添加
export const dynamic = 'force-dynamic';

const Featured = async () => {
  // 原组件代码不变
};

方案3:改用静态生成+重新验证(ISR)

如果希望页面保持静态生成特性,但需要获取最新数据,可以直接从数据源(数据库/第三方API)获取数据,而非调用自身API路由,同时配置重新验证规则:

const getData = async () => {
  // 直接调用第三方数据源或数据库,跳过自身API路由
  const res = await fetch('https://your-external-datasource.com/products', {
    cache: 'no-store',
  });

  if (!res.ok) {
    throw new Error("Failed!");
  }

  const data = await res.json();
  const validatedProducts = productArraySchema.parse(data);
  return validatedProducts;
};

然后在page.tsx中添加重新验证配置:

// 每60秒重新验证一次数据,更新静态页面
export const revalidate = 60;

const Home = () => {
  // 原页面代码不变
};

修改后的Featured组件示例(方案1)

import { productSchema } from "@/types/types";
import Image from "next/image";
import React from "react";
import { z } from "zod";
import { Button } from "../ui/button";
import { Card, CardTitle, CardContent, CardFooter } from "../ui/card";
// 导入API路由的逻辑函数
import { getProducts } from "@/app/api/products/route";

const getData = async () => {
  const data = await getProducts();
  const validatedProducts = productArraySchema.parse(data);
  return validatedProducts;
};

const productArraySchema = z.array(productSchema);
type ProductArrayType = z.infer<typeof productArraySchema>;

const Featured = async () => {
  const featuredProducts: ProductArrayType = await getData();

  return (
    <div className="grid grid-cols-2 md:grid-cols-4 lg:grid-cols-6 gap-4 mx-auto p-4 max-h-screen overflow-y-scroll">
      {featuredProducts.map((item, index) => (
        <Card key={index} className="p-1 flex flex-col space-y-1 bg-gradient-to-br from-emerald-500">
          <CardTitle className="flex justify-center p-3">
            <p>{item.title}</p>
          </CardTitle>
          <CardContent className="relative h-40">
            <Image
              src={item.img}
              fill
              sizes="(max-width: 600px) 100vw, (max-width: 600px) 50vw, 33vw"
              alt={item.title}
              className="rounded-sm absolute inset-0"
            />
          </CardContent>
          <CardFooter className="flex flex-col items-center space-y-1 justify-center">
            <p className="text-sm">{item.desc}</p>
            <p className="text-md font-semibold"><span className="px-2">price:</span>{item.price}</p>
            <Button variant="default">Add to cart</Button>
          </CardFooter>
        </Card>
      ))}
    </div>
  );
};

export default Featured;

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 03:44:56