Next.js服务端组件获取数据时触发connect ECONNREFUSED ::1:3000错误
解决Next.js服务端组件构建时本地接口连接拒绝问题
问题场景
使用Next.js 14.2.1(Node.js 18.18.1)开发时,在服务端组件中通过axios调用配置在环境变量NEXT_PUBLIC_WAITINGLIST_URL=http://localhost:3000/api的接口获取数据,构建阶段出现连接拒绝错误:connect ECONNREFUSED ::1:3000。
相关代码:
import React from "react"; import axios from "axios"; interface UsersType { id: string; firstName: string; lastName: string; email: string; } interface dataProps { allUsers: UsersType[]; } async function getData() { try { const { data } = await axios.get<dataProps>( `${process.env.NEXT_PUBLIC_WAITINGLIST_URL}/waitinglist/` ); return data; } catch (error) { console.log(error); } } export default async function Page() { const data = await getData(); return ( <div className="text-white w-100"> <table className="w-full table"> <thead> <tr className=" [&>th]:text-center [&>th]:py-3 [&>th]:px-2 "> <th>First Name</th> <th>Last Name</th> <th>Email</th> </tr> </thead> <tbody> {data?.allUsers?.map((item: UsersType) => { return ( <tr key={item?.id} className=" [&>td]:text-center [&>td]:py-3 [&>td]:px-2 " > <td>{item?.firstName}</td> <td>{item?.lastName}</td> <td>{item?.email}</td> </tr> ); })} </tbody> </table> </div> ); }
错误详情
[Error]: connect ECONNREFUSED ::1:3000 at I.from (E:\usman data\maincorenextjs.next\server\app\dashboard\admin\page.js:11:10985) at y. (E:\usman data\maincorenextjs.next\server\app\dashboard\admin\page.js:13:21276) { port: 3000, address: '::1', syscall: 'connect', code: 'ECONNREFUSED', errno: -4078, method: 'get', url: 'http://localhost:3000/api/waitinglist/', data: undefined }
原因分析
构建阶段Next.js会预渲染所有服务端组件,此时本地开发服务器(localhost:3000)并未启动,axios发起的HTTP请求自然会被拒绝。另外,NEXT_PUBLIC_前缀的环境变量是专门暴露给客户端组件的,服务端组件使用该前缀完全没必要,反而容易混淆环境变量的使用场景。
解决方案
1. 直接调用API路由的业务逻辑(推荐)
服务端组件运行在服务器端,不需要通过HTTP请求调用内部API,直接导入API路由里的核心逻辑函数即可,这样构建时无需依赖运行中的服务器,还能提升性能。
步骤:
- 把API路由的数据处理逻辑抽离到单独的文件(比如
lib/waitinglist.ts):
// lib/waitinglist.ts // 替换成你的实际数据查询逻辑,这里以Prisma操作为例 import prisma from './prisma'; export async function getAllWaitingListUsers() { const users = await prisma.waitingList.findMany({ select: { id: true, firstName: true, lastName: true, email: true, }, }); return { allUsers: users }; }
- 在服务端组件中导入并调用该函数:
import { getAllWaitingListUsers } from '@/lib/waitinglist'; export default async function Page() { const data = await getAllWaitingListUsers(); return ( {/* 原渲染逻辑不变 */} ); }
2. 区分构建/开发环境,避免无效请求
如果必须使用HTTP请求,可以在构建时返回模拟数据或跳过请求,仅在开发环境调用本地接口:
async function getData() { // 构建阶段返回默认数据或调用生产环境API if (process.env.NODE_ENV === 'production') { return { allUsers: [] }; // 或者替换为生产环境API地址: // const { data } = await axios.get('https://your-production-api.com/waitinglist/'); // return data; } try { const { data } = await axios.get<dataProps>( `${process.env.WAITINGLIST_URL}/waitinglist/` // 去掉NEXT_PUBLIC_前缀 ); return data; } catch (error) { console.log(error); return { allUsers: [] }; } }
同时修改环境变量,去掉NEXT_PUBLIC_前缀(服务端组件不需要暴露该变量给客户端):
WAITINGLIST_URL=http://localhost:3000/api
内容的提问来源于stack exchange,提问作者usmannoor90
相关产品推荐
相关产品推荐

