Next.js 13.4.12部署Vercel时遇SyntaxError: Unexpected token <错误求助
部署Vercel时Next.js 13构建失败:JSON解析错误
本地开发时项目运行正常,但部署到Vercel时构建持续失败,报错JSON解析异常。使用Next.js 13.4.12,项目包含app/projects/page.tsx和app/api/projects/route.ts,相关代码如下:
页面组件代码(app/projects/page.tsx)
const ProjectList = async () => { const baseUrl = process.env.NODE_ENV === "development" ? "http://localhost:3000" : "https://www.example.com"; const response = await fetch(`${baseUrl}/api/projects`); const data = await response.json(); const projects: Project[] = data.projects; return ( <div> {projects?.map((project) => <h1>{project?.name}</h1>)} // etc. etc. </div> ); };
API路由代码(app/api/projects/route.ts)
export async function GET() { try { // Retrieve the "projects" collection from Firestore const projectsCollection = collection(db, "projects"); const projectsSnapshot = await getDocs(projectsCollection); // Map the documents in the collection to an array of project objects const projects = projectsSnapshot.docs.map((doc) => ({ id: doc.id, ...doc.data(), })); return NextResponse.json(JSON.stringify({ projects: projects })); } catch (error) { console.error("Error retrieving projects:", error); return NextResponse.error(); } }
部署时错误信息
SyntaxError: Unexpected token < in JSON at position 0 11:13:00.318 at JSON.parse (<anonymous>) 11:13:00.318 at parseJSONFromBytes (node:internal/deps/undici/undici:6571:19) 11:13:00.318 at successSteps (node:internal/deps/undici/undici:6545:27) 11:13:00.319 at node:internal/deps/undici/undici:1211:60 11:13:00.319 at node:internal/process/task_queues:140:7 11:13:00.319 at AsyncResource.runInAsyncScope (node:async_hooks:203:9) 11:13:00.319 at AsyncResource.runMicrotask (node:internal/process/task_queues:137:8) 11:13:00.319 at process.processTicksAndRejections (node:internal/process/task_queues:95:5) 11:13:00.336 11:13:00.336 Error occurred prerendering page "/". Read more: https://nextjs.org/docs/messages/prerender-error 11:13:00.336 SyntaxError: Unexpected token < in JSON at position 0 11:13:00.336 at JSON.parse (<anonymous>) 11:13:00.336 at parseJSONFromBytes (node:internal/deps/undici/undici:6571:19) 11:13:00.337 at successSteps (node:internal/deps/undici/undici:6545:27) 11:13:00.340 at node:internal/deps/undici/undici:1211:60 11:13:00.340 at node:internal/process/task_queues:140:7 11:13:00.340 at AsyncResource.runInAsyncScope (node:async_hooks:203:9) 11:13:00.340 at AsyncResource.runMicrotask (node:internal/process/task_queues:137:8) 11:13:00.340 at process.processTicksAndRejections (node:internal/process/task_queues:95:5) 11:13:00.340 11:13:00.340 > Export encountered errors on following paths: 11:13:00.340 /page: / 11:13:00.340 - info Generating static pages (5/5) 11:13:00.398 Error: Command "npm run build" exited with 1
解决方案
1. 修复API路由的JSON返回逻辑
NextResponse.json()会自动将传入的对象序列化为JSON字符串,不需要手动调用JSON.stringify。手动序列化会导致返回的数据是字符串形式的JSON,客户端解析时会出错。修改API路由:
// 替换原来的return语句 return NextResponse.json({ projects: projects });
2. 移除服务器组件中的外部URL调用
在App Router的服务器组件中,调用内部API直接使用相对路径即可,无需拼接完整域名。构建预渲染阶段,外部URL可能无法正常访问,导致返回HTML错误页面(这就是错误中Unexpected token <的原因——返回的是HTML而非JSON)。修改页面组件:
const ProjectList = async () => { // 直接使用相对路径调用内部API const response = await fetch('/api/projects'); const data = await response.json(); const projects: Project[] = data.projects; return ( <div> {projects?.map((project) => <h1>{project?.name}</h1>)} // etc. etc. </div> ); };
3. 更优方案:直接在服务器组件中调用Firestore
既然是服务器组件,完全可以跳过API路由,直接在组件内获取Firestore数据,减少额外请求,也避免此类跨环境问题:
const ProjectList = async () => { try { const projectsCollection = collection(db, "projects"); const projectsSnapshot = await getDocs(projectsCollection); const projects: Project[] = projectsSnapshot.docs.map((doc) => ({ id: doc.id, ...doc.data(), })); return ( <div> {projects?.map((project) => <h1>{project?.name}</h1>)} </div> ); } catch (error) { console.error("Error retrieving projects:", error); return <div>Failed to load projects</div>; } };
内容的提问来源于stack exchange,提问作者PP24
相关产品推荐
相关产品推荐

