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

Next.js 13 App Router部署Vercel时内部API请求失败

Next.js 13 App Router 部署与数据传递问题解决

问题1:本地/api调用正常,部署到Vercel后无法获取数据

相关代码

Server Component代码:

const getAvailableSlots = async () => {
  const res = await fetch(
    `${process.env.NEXT_PUBLIC_API_URL}/api/availabilityList`
  );
  if (!res.ok) {
    console.log(res);
  }

  return res.json();
};

const Appointments = async () => {
  const data = await getAvailableSlots();
  return (
    <div className="App">
      <div>
        <AppointmentsPage data={data} />
      </div>
    </div>
  );
};

export default Appointments;

/api路由代码:

const handler = async (req, res) => {
  await connectDB();
  console.log("Connected to Mongo");
  try {
    const availiblityList = await Users.find();
    res.status(200).send(availiblityList);
  } catch (error) {
    res.status(400).send(error.message);
  }
};

export default handler;

问题原因

  1. Server Component中fetch路径错误:Server Component的fetch在服务器端执行,无需依赖外部域名的完整URL,若NEXT_PUBLIC_API_URL在Vercel上仍配置为localhost,会导致请求失败。
  2. Mongoose文档未正确序列化:Users.find()返回的是Mongoose文档对象数组,直接用res.send()无法完成JSON序列化,Vercel环境下会引发数据传递异常。

解决方案

  1. 修改Server Component的fetch路径为相对路径,无需外部域名:
// 根据业务需求配置缓存策略,比如no-store避免缓存旧数据
const res = await fetch('/api/availabilityList', { cache: 'no-store' });
  1. 更新/api路由,将Mongoose文档转为纯JS对象并使用res.json()返回:
const handler = async (req, res) => {
  await connectDB();
  try {
    // .lean()让Mongoose直接返回纯JS对象,而非文档实例
    const availiblityList = await Users.find().lean();
    res.status(200).json(availiblityList);
  } catch (error) {
    res.status(400).json({ message: error.message });
  }
};

export default handler;

问题2:直接调用getData传递数据时出现警告,无法重新加载

相关代码

Server Component代码:

import { getData } from "../../pages/api/availabilityList";

const getAvailableSlots = async () => {
  const res = await getData();
  return res;
};

const Appointments = async () => {
  const data = await getAvailableSlots();
  console.log(data);
  return (
    <div className="App">
      <div className="section section0 fp-auto-height-responsive items-center">
        <AppointmentsPage data={data} />
      </div>
    </div>
  );
};

export default Appointments;

/api路由补充代码:

export async function getData() {
  await connectDB();

  const response = await Users.find();
  return response;
}

const handler = async (req, res) => {
  const jsonData = await getData();
  res.status(200).json(jsonData);
};

export default handler;

警告信息(翻译后)

警告:只能将纯对象从服务器组件传递给客户端组件。不支持带有toJSON方法的对象。在传递给props之前,请手动将其转换为简单值。 [{$__: ..., $isNew: false, _doc: ...}, ...]

问题原因

getData中Users.find()返回的是Mongoose文档实例数组,这类对象包含Mongoose内部属性和toJSON方法,并非纯JS对象。当Server Component将其传递给Client Component(AppointmentsPage)时,Next.js会触发序列化警告,且数据无法正常更新,导致无法重新加载。

解决方案

修改getData方法,通过.lean()将Mongoose文档转为纯JS对象:

export async function getData() {
  await connectDB();

  // 使用.lean()获取纯JS对象数组,避免序列化问题
  const response = await Users.find().lean();
  return response;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 14:50:16