Next.js 13 App Router构建报错:服务端组件调用API路由失败
问题原因
在Next.js构建阶段(yarn run build),本地开发服务器并未启动,此时页面组件中通过fetch调用自身API路由(如http://localhost:3000/api/categories)会失败——因为没有运行中的服务器来响应这个请求。而开发环境(yarn run dev)下服务器处于启动状态,所以能正常工作。
解决方案:复用数据获取逻辑
最合理的做法是将数据获取逻辑抽离成共享函数,让API路由和页面组件直接调用该函数,避免通过HTTP请求绕圈。这样既保持代码整洁,又能正常完成构建。
步骤1:创建共享数据服务文件
在app/lib目录下创建categories.ts文件(若lib目录不存在则新建),编写Prisma查询逻辑:
// app/lib/categories.ts import prisma from '@/lib/prisma'; // 假设你的Prisma客户端实例在此路径 export async function getCategories() { return await prisma.categories.findMany(); }
步骤2:更新API路由
修改/api/categories/route.ts,使用共享函数代替直接编写Prisma查询:
// app/api/categories/route.ts import { getCategories } from '@/app/lib/categories'; export async function GET() { const categories = await getCategories(); return new Response(JSON.stringify(categories)); }
步骤3:更新页面组件
修改page.tsx,直接调用共享函数获取数据,不再使用fetch:
// app/page.tsx import { getCategories } from '@/app/lib/categories'; export default async function Home() { const categories = await getCategories(); console.log(categories); return ( <main> <h1>Home</h1> </main> ); }
其他可选方案(不推荐)
如果因特殊需求必须保留API调用,可以考虑以下方式,但会牺牲部分性能或静态生成能力:
- 客户端渲染:在
page.tsx顶部添加'use client',将页面改为客户端组件。此时构建阶段不会执行fetch,但页面会变为客户端渲染,失去静态生成的优势。 - 动态渲染:使用
fetch时添加cache: 'no-store',强制页面在每次请求时进行服务器端渲染。这样构建阶段不会预渲染该页面,但会增加服务器负载。
内容的提问来源于stack exchange,提问作者Илья Маковецкий
相关产品推荐
相关产品推荐

