FastAPI + Vue3 + Vite 跨域报错全解:从 `Access-Control-Allow-Origin missing` 到彻底修复

第一步:发现错误(What Broke?)

报错信息原文:

错误原因:

CORS 跨域错误:缺少 / 无效 Access-Control-Allow-Origin 响应头

你遇到的是前端跨域请求被浏览器拦截的标准问题,核心原因:后端没有返回合法的 Access-Control-Allow-Origin 响应头,浏览器安全策略直接阻止了请求。


第二步:解决错误

我们首先查看前端 api.jsvite.config.js 文件。

这两个文件是 Vue3 + Vite 项目中的核心配置文件,分别负责项目构建环境配置和前端 API 接口统一管理。以下是详细的功能拆解:


1. vite.config.js ------ 项目构建与开发服务配置

这是 Vite 构建工具的核心配置文件,用于定义项目的构建规则、插件挂载和开发服务器参数。

js 复制代码
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

// 导出 Vite 配置
export default defineConfig({
  // 注册 Vue 官方插件,用于支持 Vue3 单文件组件(.vue)的编译解析
  plugins: [vue()],
})

核心功能

  • 插件管理 :通过 plugins 数组挂载 Vite 官方 / 第三方插件(这里是 @vitejs/plugin-vue,支持 Vue3 语法编译)。
  • 基础构建配置:可扩展配置端口号、跨域代理、环境变量、打包输出路径、依赖预构建等(当前为初始默认配置)。
  • 环境适配:区分开发环境 / 生产环境的构建逻辑,是 Vite 项目的 "配置中枢"。

2. api.js ------ 前端 API 统一配置管理

这是前端项目的接口配置中心,用于统一管理后端接口地址、第三方 API 密钥、请求基础路径等公共参数,避免代码中硬编码 URL / 密钥。

核心代码解析

js 复制代码
// 后端API基础URL配置(本地后端服务地址)
export const apiConfig = {
  baseURL: 'http://127.0.0.1:8009',
}

// 第三方AI接口配置(阿里通义千问)
export const aiChatConfig = {
  apiEndpoint: 'https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions',
  apiKey: 'sk-9c4d89982a6a4bd3b7494d94751fe81c',
  model: 'qwen3-max-preview'
}

核心功能

  • 后端接口统一管理 :将后端服务的基础地址抽离为 baseURL,后续接口请求只需基于该地址拼接路径,方便后端地址更换时只改一处。
  • 第三方 API 配置 :集中存储阿里通义千问 AI 对话接口的端点、API 密钥(apiKey)、调用模型(model),避免在业务代码中直接暴露敏感信息。
  • 配置解耦:将所有接口相关的公共参数集中管理,降低代码维护成本,方便不同环境(开发 / 测试 / 生产)切换时快速调整配置。

关联说明

vite.config.js 可通过配置 server.proxy 实现前端跨域代理,间接解决跨域问题(比如将 /api 请求转发到 http://127.0.0.1:8009);而 api.js 中的 baseURL 则是接口请求的基础地址,两者配合可实现前端接口请求的规范化和跨域处理。


1. api.js 修改前后对比

修改前

js 复制代码
export const apiConfig = {
  baseURL: 'http://127.0.0.1:8009', // 直接写后端完整地址
}
export const aiChatConfig = {
  apiEndpoint: 'https://dashscope.aliyuncs.com/...',
  apiKey: 'sk-xxxx',
  model: 'qwen3-max-preview'
}

修改后

js 复制代码
export const apiConfig = {
  baseURL: '/api', // 改成相对路径 /api
};
export const aiChatConfig = {
  baseURL: '/api', // 也改成相对路径 /api
};

🎯 为什么这么改?

  • 解决跨域(CORS)的核心前提 :浏览器的同源策略会拦截「前端域名(localhost:5173)」和「后端域名(127.0.0.1:8009)」端口不同的请求。把 baseURL 改成相对路径 /api,是为了让前端请求走 Vite 代理,而不是直接请求后端地址,从根源上绕开浏览器的跨域拦截。
  • 统一请求入口 :所有以 /api 开头的请求,都会被 Vite 自动转发到后端,前端代码里不用再写死 IP 和端口,后续部署到服务器时,只需要改 vite.config.jstarget,前端代码完全不用动,更易维护。
  • 修复了「找不到导出」的报错 :你之前的 aiChatConfig 是阿里云通义千问的配置,项目里的 AIChat.vue 等文件在导入时,会因为你修改了配置结构导致找不到导出。把 aiChatConfig 也改成 baseURL: '/api',是为了让 AI 聊天接口也走代理,同时保证导出结构和项目导入代码完全匹配,彻底解决 No matching export 报错。

2. vite.config.js 修改前后对比

修改前

js 复制代码
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
  plugins: [vue()],
})

修改后

js 复制代码
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
  plugins: [vue()],
  // 新增:跨域代理
  server: {
    proxy: {
      '/api': {
        target: 'http://127.0.0.1:9000', // 后端地址
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\/api/, '')
      }
    }
  },
  // 新增:忽略 fsevents 错误
  optimizeDeps: {
    exclude: ['fsevents']
  }
})

为什么这么改?

① 新增 server.proxy 代理配置

核心作用 :实现「前端请求 /api/xxx → Vite 转发到 http://127.0.0.1:9000/xxx

关键参数解释

  • target:后端服务的真实地址(注意你这里改成了 9000 端口,要和后端实际启动的端口一致!)
  • changeOrigin: true:修改请求头的 Origin,让后端认为请求来自同源,避免跨域校验
  • rewrite:把请求路径里的 /api 去掉,比如 /api/news 会被转发为 /news,和后端接口路径匹配
② 新增 optimizeDeps.exclude: ['fsevents']

核心作用 :解决 Windows 系统下的 fsevents.node 报错

原理fsevents 是 Mac 系统专用的文件监听库,Windows 系统不支持,Vite 会尝试加载它导致报错。

加这一行后,Vite 会直接忽略这个依赖,不再尝试加载,彻底消除这个无关报错。


必须在 FastAPI 中添加 CORS 中间件!

main.py 代码(必须修改)

python 复制代码
# main.py
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

# 添加 CORS 中间件(关键!)
app.add_middleware(
    CORSMiddleware,
    # 前端运行地址(Vite 默认 5173)我的电脑默认
    allow_origins=["*"],#开发写型号没问题,部署时需要修改
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)
# 示例接口
@app.get("/")
async def root():
    return {"message": "Hello World"}

重点解释:

配置项 说明
allow_origins=["http://localhost:5173"] 前端地址,必须精确匹配 ,不能用 *(安全风险)
allow_credentials=True 支持 token、cookie
allow_methods=["*"] 所有 HTTP 方法(GET/POST)
allow_headers=["*"] 所有请求头

第六步:重启服务

bash 复制代码
uvicorn main:app --reload --port 9000

重启后,FastAPI 会加载 CORS 中间件


第七步:重启前端

bash 复制代码
npm run dev

打开浏览器:http://localhost:5173


第八步:验证结果(Confirm Fix)

打开浏览器开发者工具 → Network

项目 是否正常
请求路径 http://localhost:5173/api/news
实际地址 http://127.0.0.1:9000/api/news(代理)
状态码 200 OK
Headers ✅ 包含 Access-Control-Allow-Origin: http://localhost:5173
Response ✅ JSON 数据正常显示

最后总结:错误解决全链路

步骤 内容 实际意义
1. 发现错误 Access-Control-Allow-Origin: missing 现象:数据被屏蔽
2. 分析错误 代理没问题,curl 能通 → 问题在头 锁定为后端缺失 CORS
3. 排查错误 curl 测试 → 无 CORS 头 确认后端未返回头
4. 定位根因 FastAPI 默认不提供 CORS 头 你漏了 CORSMiddleware
5. 解决错误 main.py 添加 CORS 中间件 ✅ 修复成功
6. 验证结果 数据正常加载,CORS 头存在 ✅ 问题彻底解决

相关推荐
热爱编程的小李3 小时前
UniApp 实现 H5/Android/uniapp原生 三端 MinIO 预签名 PUT 直传方案
状态模式
李昊哲小课2 天前
fastapi sse websocket 奶茶店实时订单看板
人工智能·python·websocket·网络协议·fastapi·sse
Crazy________2 天前
k8s部署若依微服务架构流程,v3.6.6
运维·云原生·容器·kubernetes·状态模式
fīɡЙtīиɡ ℡2 天前
怎么是用JWT
java·状态模式
李昊哲小课2 天前
fastapi sse websocket 智能家居实时控制台
python·websocket·智能家居·fastapi·sse
赵广陆2 天前
SQLAlchemy ORM 超全教程
python·fastapi
ThsPool2 天前
【ENVI二次开发学习整理 02】IDL语言基础与程序设计
学习·中间件
程序员良辰2 天前
【TongWeb7】启动接近两分钟问题排查
java·开发语言·中间件
为啥全要学2 天前
fastapi websocket全双工通信
websocket·网络协议·fastapi
这就是佬们吗2 天前
企业Agent落地为什么需要RAG?
人工智能·python·fastapi