NextJS 13 App Dir服务器组件构建报错,Vercel部署求助
Next.js 13 App Directory(Beta)部署Vercel时Fetch请求失败
问题背景
使用Next.js 13 Beta版App Directory功能+TypeScript开发站点,本地运行完全正常,所有fetch请求均能正常工作,但部署到Vercel时,CLI生成静态页面阶段fetch请求崩溃,4个服务器组件(About、WorkExperience、Skills、Projects)均报相同错误。
错误日志
(node:457) ExperimentalWarning: The Fetch API is an experimental feature. This feature could change at any time (Use `node --trace-warnings ...` to show where the warning was created) TypeError: fetch failed at Object.fetch (node:internal/deps/undici/undici:11118:11) at process.processTicksAndRejections (node:internal/process/task_queues:95:5) at async fetchPageInfo (/vercel/path0/.next/server/app/page.js:664:20) at async About (/vercel/path0/.next/server/app/page.js:679:18) { cause: Error: connect ECONNREFUSED 127.0.0.1:3000 at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1300:16) at TCPConnectWrap.callbackTrampoline (node:internal/async_hooks:130:17) { errno: -111, code: 'ECONNREFUSED', syscall: 'connect', address: '127.0.0.1', port: 3000 } }
相关代码
page.tsx
import { Experience, PageInfo, Project, Skill, Social, } from "@/pages/api/typings"; import About from "./Components/about"; import Contact from "./Components/contact"; import WorkExperience from "./Components/experience"; import Header from "./Components/header"; import Hero from "./Components/hero"; import Projects from "./Components/projects"; import Skills from "./Components/skills"; type Props = { pageInfo: PageInfo; experiences: Experience; skills: Skill[]; projects: Project[]; socials: Social[]; }; export default function Home() { return ( <main className="h-screen snap-y snap-mandatory overflow-scroll bg-background z-0 scrollbar scrollbar-track-textColour scrollbar-thumb-menuColour"> <Header /> <section className="snap-center"> <Hero /> </section> <section className="snap-center" id="about"> {/* @ts-expect-error Server Component */} <About /> </section> <section className="snap-center" id="experience"> {/* @ts-expect-error Server Component */} <WorkExperience /> </section> <section className="snap-center" id="skills"> {/* @ts-expect-error Server Component */} <Skills /> </section> <section className="snap-start" id="projects"> {/* @ts-expect-error Server Component */} <Projects /> </section> <section className="snap-start" id="contact"> <Contact /> </section> </main> ); }
额外信息
- About、WorkExperience、Skills、Projects为服务器组件,其余组件因使用状态标记为客户端组件
- 已确认目录路径正确,所有.env变量已声明且可用
- 尝试过VSCode CLI构建、GitHub Web UI构建,均未解决问题
解决方案
核心原因
部署阶段(静态生成)时,服务器组件中的fetch请求尝试访问127.0.0.1:3000,但此时本地服务器并未运行,导致连接被拒绝。本地运行时服务器已启动,所以请求正常。
修复步骤
直接调用数据逻辑,跳过本地API路由
服务器组件可以直接执行数据获取逻辑(如数据库查询、第三方SDK调用),无需通过API路由中转。把API路由里的业务逻辑抽成独立函数,放在lib目录下,在服务器组件中直接调用该函数,替代fetch('http://localhost:3000/api/xxx')的写法。用环境变量配置API地址(若必须保留API路由)
在Vercel部署时,API的实际地址是站点域名,而非localhost。添加环境变量API_BASE_URL:- 本地开发时设为
http://localhost:3000 - Vercel部署时设为你的站点域名(如
https://your-site.vercel.app)
然后在fetch时使用process.env.API_BASE_URL + '/api/xxx'拼接地址。
- 本地开发时设为
遵循App Router数据获取规范
Next.js 13 App Directory中,服务器组件支持直接用async/await在组件内部获取数据,确保数据获取逻辑在服务器端执行,避免依赖本地运行的开发服务器。
验证方法
本地执行next build命令测试,若构建成功,说明问题已修复,再部署到Vercel即可。
内容的提问来源于stack exchange,提问作者FimbulWinters
相关产品推荐
相关产品推荐

