Nuxt3页面刷新时出现ECONNREFUSED错误,HMR模式下正常
Nuxt3 页面刷新时数据获取失败(HMR模式正常)
问题详情
将基于私有仓库的公开GitHub仓库迁移升级到Nuxt3,使用反向代理指向目标Docker镜像。页面数据获取代码如下:
<script setup> const runtimeConfig = useRuntimeConfig() const { data: app, pending, error, refresh } = await useAsyncData(() => $fetch(`${runtimeConfig.public.BASE_API_BROWSER_URL}/message`) ) </script>
改用useFetch替代useAsyncData会出现完全相同的问题。
异常表现
- 代码变更后通过HMR热加载页面时,数据获取完全正常
- 手动刷新页面时,触发报错:
Error: request to http://localhost/api/message failed, reason: connect ECONNREFUSED 127.0.0.1:80 ()
- 直接将报错中的URL复制到浏览器可正常访问接口,仅页面刷新场景下失效
已尝试添加客户端错误重试代码,但未解决根本问题:
if (process.client && error.value) { await refresh() }
原因分析与解决方案
1. 服务端渲染时的请求目标错配
Nuxt3在页面刷新时会触发服务端渲染(SSR),此时$fetch会在Nuxt服务端容器内执行。容器内的localhost指向容器自身,而非宿主机的反向代理地址——这就是刷新失败的核心原因。而HMR模式下页面是纯客户端渲染,请求从浏览器发向宿主机的localhost,因此能正常访问。
解决方法:
在nuxt.config.ts中区分配置服务端与客户端的API地址:
export default defineNuxtConfig({ runtimeConfig: { // 服务端使用的API地址:指向Docker网络内的后端服务名,或宿主机的局域网IP BASE_API_SERVER_URL: 'http://backend-service:8080/api', public: { // 客户端使用的API地址:浏览器可直接访问的地址 BASE_API_BROWSER_URL: 'http://localhost/api' } } })
页面中根据运行环境选择对应地址:
<script setup> const runtimeConfig = useRuntimeConfig() const apiBaseUrl = process.server ? runtimeConfig.BASE_API_SERVER_URL : runtimeConfig.public.BASE_API_BROWSER_URL const { data: app, pending, error, refresh } = await useAsyncData(() => $fetch(`${apiBaseUrl}/message`) ) </script>
2. 调整Docker网络配置(针对容器部署场景)
如果使用Docker Compose编排服务,确保Nuxt容器和后端服务在同一个自定义网络中,这样服务端可以直接通过服务名访问后端,无需走宿主机反向代理:
services: nuxt-app: build: . networks: - app-internal-network backend-service: image: your-backend-image networks: - app-internal-network networks: app-internal-network: driver: bridge
3. 临时方案:禁用页面SSR
如果业务不需要服务端渲染,可以在页面或全局禁用SSR,强制所有请求从客户端发起:
- 页面级禁用:
<script setup> definePageMeta({ ssr: false }) </script>
- 全局禁用:
export default defineNuxtConfig({ ssr: false })
内容的提问来源于stack exchange,提问作者DevWizard
相关产品推荐
相关产品推荐

