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 小时前
jeecg预览pdf、jeecg无法预览pdf、jeecg自带预览pdf
pdf·状态模式
爱吃烤鸡翅的酸菜鱼4 小时前
Java 事件发布-订阅机制全解析:从原生实现到主流中间件
java·中间件·wpf·事件·发布订阅
jwn9994 小时前
Laravel 6.x核心特性深度解析
状态模式
my_styles4 小时前
linux系统下安装 tengine / 宝兰德等国产信创中间件和闭坑
linux·运维·服务器·spring boot·nginx·中间件
ZHENGZJM4 小时前
Gin 鉴权中间件设计与实现
中间件·gin
Chase_______4 小时前
【FastAPI】内网/离线环境docs文档无法显示的解决方案
fastapi
帐篷Li5 小时前
CPS统计数据汇总 实现计划
状态模式
onebyte8bits5 小时前
NestJS 系列教程(十八):文件上传与对象存储架构(Multer + S3/OSS + 访问控制)
前端·架构·node.js·状态模式·nestjs
小李云雾5 小时前
FastAPI 后端开发:文件上传 + 表单提交
开发语言·python·lua·postman·fastapi