如何在Nuxt3插件中配置$fetch的baseURL(自定义fetch)
解决Nuxt customFetch插件刷新页面时的Invalid URL错误及环境化baseURL配置
问题原因
刷新页面时触发服务端渲染(SSR),此时浏览器直接发起页面请求,请求头中没有referer字段,导致new URL(undefined)抛出TypeError [ERR_INVALID_URL]: Invalid URL错误。而路由跳转是客户端导航,不会执行服务端的这段逻辑,所以无报错。
另外,你原代码的baseURL逻辑不符合需求:你需要按环境分支配置固定的API地址,但原代码是取当前页面的origin,这和环境分支无关,会导致环境切换时baseURL不匹配。
解决方案
1. 用环境变量配置不同环境的baseURL(最优解)
Nuxt支持通过环境变量区分不同环境,这是配置多环境API地址的标准方式:
在项目根目录创建对应环境的.env文件:
- 本地开发(.env):
NUXT_PUBLIC_API_BASE_URL=https://localhost:3000 - 预发布环境(.env.dev):
NUXT_PUBLIC_API_BASE_URL=https://123.com - 生产环境(.env.prod):
NUXT_PUBLIC_API_BASE_URL=https://abc.com
- 本地开发(.env):
修改customFetch插件代码,直接读取环境变量:
import { ofetch } from 'ofetch' const fetcher = ofetch.create({ // 可添加全局配置,比如默认headers、超时时间等 }) export default defineNuxtPlugin((nuxtApp) => { const customFetch = async (request, options) => { // 从环境变量获取baseURL,兜底值用本地地址 const baseURL = process.env.NUXT_PUBLIC_API_BASE_URL || 'https://localhost:3000' const response = await fetcher.raw(request, { ...options, baseURL }) return response._data } nuxtApp.provide('customFetch', customFetch) })启动项目时指定环境(根据你的CI/CD流程调整):
- 本地:
npm run dev(默认加载.env) - 预发布:
NUXT_ENV=dev npm run build(加载.env.dev) - 生产:
NUXT_ENV=prod npm run build(加载.env.prod)
- 本地:
2. 修复原逻辑的错误(不推荐,仅用于保留原逻辑场景)
如果你一定要保留基于origin的逻辑,需要在服务端判断referer是否存在,避免传入undefined给new URL:
import { ofetch } from 'ofetch' const fetcher = ofetch.create({ // set options... }) export default defineNuxtPlugin(async (nuxtApp) => { const customFetch = async (request, options) => { let baseURL if (process.server) { const referer = nuxtApp?.ssrContext?.event?.node?.req?.headers?.referer // 若referer不存在,兜底用环境变量或固定地址 baseURL = referer ? new URL(referer).origin : process.env.NUXT_PUBLIC_API_BASE_URL || 'https://localhost:3000' } else { baseURL = window.location.origin } const response = await fetcher.raw(request, { ...options, baseURL }) return response._data } nuxtApp.provide('customFetch', customFetch) })
关键说明
- 环境变量
NUXT_PUBLIC_前缀会让变量同时暴露给服务端和客户端,适合API地址这类需要两端都用到的配置。 - 依赖referer头不可靠:除了刷新页面,用户直接输入地址、书签访问等场景都可能没有referer,导致baseURL异常。
内容的提问来源于stack exchange,提问作者LSS
相关产品推荐
相关产品推荐

