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;
问题原因
- Server Component中fetch路径错误:Server Component的fetch在服务器端执行,无需依赖外部域名的完整URL,若
NEXT_PUBLIC_API_URL在Vercel上仍配置为localhost,会导致请求失败。 - Mongoose文档未正确序列化:
Users.find()返回的是Mongoose文档对象数组,直接用res.send()无法完成JSON序列化,Vercel环境下会引发数据传递异常。
解决方案
- 修改Server Component的fetch路径为相对路径,无需外部域名:
// 根据业务需求配置缓存策略,比如no-store避免缓存旧数据 const res = await fetch('/api/availabilityList', { cache: 'no-store' });
- 更新/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
相关产品推荐
相关产品推荐

