惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

S
SegmentFault 最新的问题
MongoDB | Blog
MongoDB | Blog
J
Java Code Geeks
Stack Overflow Blog
Stack Overflow Blog
The GitHub Blog
The GitHub Blog
博客园 - Franky
博客园 - 叶小钗
大猫的无限游戏
大猫的无限游戏
V
Visual Studio Blog
IT之家
IT之家
美团技术团队
博客园 - 司徒正美
Martin Fowler
Martin Fowler
Last Week in AI
Last Week in AI
酷 壳 – CoolShell
酷 壳 – CoolShell
Vercel News
Vercel News
雷峰网
雷峰网
B
Blog
WordPress大学
WordPress大学
aimingoo的专栏
aimingoo的专栏
D
Docker
P
Proofpoint News Feed
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
爱范儿
爱范儿

博客园 - 一名程序媛呀

Anki插件开发必知必会:钩子函数与右键菜单定制 httpx 传参总报错?这次把 GET、POST、文件上传到响应处理的坑给你一次填平 从卡顿到丝滑:FastAPI 调用外部 API 的正确姿势(httpx 实战) 还在 XHR、Fetch 和 Axios 之间纠结?我踩过的坑,希望你一个都不用碰到 你的REST接口还在“过度投喂”数据吗?——FastAPI + GraphQL实战避坑指南 Uvicorn、Gunicorn 傻傻分不清?FastAPI 生产部署避坑指南 Termux里的二进制和脚本,到底怎么运行才不踩坑?Termux-service 保活妙招! 刚部署的 LibreTranslate 频频翻车?我掏出了 20 年前的 StarDict 词典,用 FastAPI 搭了个本地词典翻译 API 别再用网页翻译看源码了!你的私人翻译神器LibreTranslate,部署避坑指南来了 掏出手机就能搭个 WebDAV 同步服务器?这操作有点香 别只盯着GitBook了!这个文档神器让你的笔记秒变网站 写爬虫时用了代理还被封?Python 代理的那些隐藏坑,我替你踩明白了 FastAPI 身份验证总踩坑?这份 FastAPI Users “避坑指南”请收好 旧手机别扔!用 Termux 搭个私人云盘,比网盘香多了 你的FastAPI又在服务器上“跑不起来”了?来,今天咱把打包这件事彻底聊透 写页面时别再把 Element Plus 整个搬进来啦!Vue3按需加载的坑我帮你踩平了 前端包管理咋选?我从npm叛逃到pnpm的血泪史(附避坑指南) 聊聊 fetch 使用中我踩过的那些坑和正确打开方式 FastApiAdmin 后端接口开发好了,前端管理界面怎么调用与显示? 给 FastApiAdmin 加个“会议纪要”模块,我把后端二次开发的坑踩了个遍 我用了FastApiAdmin后,连夜把踩过的坑都整理出来了 告别 Typora 后的新欢:我把所有笔记迁移到了 Obsidian 这个“第二大脑” 你的Agent API还在裸奔?从认证到沙箱,我用FastAPI搭了几道防线 让 FastAPI Agent 思考不阻塞:手把手教你实现异步任务与后台处理方案 让FastAPI Agent真正记住你:聊聊会话记忆与持久化存储的落地实践 FastAPI Agent 函数调用实战:我让 AI 学会了“自己动手查天气“ 初探:用 FastAPI 搭建你的第一个 AI Agent 接口 FastAPI 少有人提的实用技巧:把 Depends 依赖提到路由层,代码少写60% FastAPI 生产环境静态文件完全指南:从 /favicon.ico 404 到 HSTS 混合内容,一次全根治 用了loguru我才明白,Python日志还能这么写
FastAPI + Vue 前后端分离实战:我的项目结构“避坑指南”
一名程序媛呀 · 2026-04-07 · via 博客园 - 一名程序媛呀

你写好了丝滑的FastAPI后端,Vue前端也跑得欢,但一联调就炸?

跨域、路由冲突、环境变量混乱……这些问题我当初全踩过。最惨一次,前后端联调花了整整三天,结果只是axios配置里少写了一个斜杠。今天就跟你好好聊聊FastAPI+Vue前后端分离的正确姿势,全是实战经验,不是那种抄官方文档的教程。

📌 文章脉络

🔸 一个让你血压飙升的联调场景

🔸 我的“强迫症”项目结构(直接拿去用)

🔸 通信的3个核心配置(少一个都会炸)

🔸 开发环境 vs 生产环境:别再手改baseURL了!

🔸 那些文档不会告诉你的“隐形坑”

🔸 进阶思考:拆分vs聚合,你的项目适合哪种?

🚨 先还原一个真实“案发现场”

小张花了一周写完FastAPI接口,用Postman测试全部通过,美滋滋地去睡了个好觉。第二天起床,信心满满地启动Vue项目,npm run dev,然后……控制台一片红Access-Control-Allow-Origin 错误。

赶紧上网搜,装了个flask-cors?不对,我是FastAPI。手忙脚乱加上CORSMiddleware,跨域是解决了,但POST请求又报422 Unprocessable Entity——前端传的JSON格式后端不认。

你可能会问:不就是配置个代理、写个接口吗?错!前后端分离的“分离”二字,坑全藏在细节里。下面我把最终稳定运行的结构和配置贴出来,你直接复制粘贴就能跑。

📁 我的“强迫症”项目结构(治好了我的精神内耗)

以前我喜欢把所有文件堆在一个文件夹里,后来发现维护起来像在垃圾堆里找钥匙。现在的结构长这样,按功能拆分明细,但又不至于过度拆分(别学我一开始拆了20个文件夹,结果自己都找不到东西)。

fastapi_vue_project/
├── backend/                 # FastAPI后端
│   ├── app/
│   │   ├── api/            # 路由层(按模块分)
│   │   │   ├── v1/
│   │   │   │   ├── users.py
│   │   │   │   └── tasks.py
│   │   ├── core/           # 配置、安全、数据库连接
│   │   │   ├── config.py
│   │   │   └── database.py
│   │   ├── models/         # SQLAlchemy模型
│   │   ├── schemas/        # Pydantic模型(请求/响应结构)
│   │   ├── services/       # 业务逻辑层
│   │   └── main.py         # 入口
│   ├── requirements.txt
│   └── .env                # 环境变量(别提交到git!)
├── frontend/               # Vue3前端
│   ├── src/
│   │   ├── api/           # 封装axios请求
│   │   ├── views/         # 页面
│   │   ├── router/        # 路由
│   │   └── utils/         # 工具函数
│   └── .env.development   # 开发环境变量
│   └── .env.production    # 生产环境变量
└── docker-compose.yml      # 可选,线上部署用
        

👆 这个结构我用了很久,大小项目都稳得很。关键是 core/config.py frontend/.env.* 这对“黄金搭档”,解决了90%的环境切换问题。

🔌 通信的3个核心配置(少一个都连不上)

1️⃣ FastAPI的CORS中间件(不是加一行就完事的)

很多人复制官方示例allow_origins=["*"]就跑了,但生产环境千万别这么干!而且你还要注意allow_credentialsallow_headers的配合。

# backend/app/core/config.py
class Settings:
    BACKEND_CORS_ORIGINS = ["http://localhost:5173", "http://127.0.0.1:5173"]  # 开发环境
    # 生产环境从环境变量读取,不要写死

# backend/app/main.py
from fastapi.middleware.cors import CORSMiddleware

app.add_middleware(
    CORSMiddleware,
    allow_origins=settings.BACKEND_CORS_ORIGINS,  # 注意!不是 "*"
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["Authorization", "Content-Type"],
)

这里有个坑:如果你前端用axios带上了withCredentials: true,后端allow_origins就不能是["*"],必须指定具体域名。当初我在这里卡了4个小时,最后翻FastAPI源码才找到原因。

2️⃣ Vue的代理配置(开发神器,但别滥用)

Vite(或webpack)的proxy配置简直是开发阶段的救星,让你彻底告别跨域烦恼。但很多人抄完配置就不管了,结果部署到生产环境又报错。

// frontend/vite.config.js
export default defineConfig({
  server: {
    proxy: {
      '/api': {
        target: 'http://localhost:8000',  // FastAPI默认端口
        changeOrigin: true,
        rewrite: (path) => path.replace(/^\/api/, '')  // 注意这个重写规则!
      }
    }
  }
})        

注意看rewrite这一行:如果你的FastAPI路由是@app.get("/users"),前端请求/api/users,代理会把/api去掉再转发。这里写错了路径,就会404。

3️⃣ 统一的响应格式(别让前端猜你返回什么)

这是我最想吐槽的一点:很多人后端返回的数据结构每天不一样,今天{"data": {...}},明天{"result": {...}}。前端大哥没被你气死算我输。

我的习惯:统一用下面的格式

# backend/app/schemas/common.py
from pydantic import BaseModel
from typing import Generic, TypeVar, Optional

T = TypeVar('T')

class ResponseModel(BaseModel, Generic[T]):
    code: int = 200
    message: str = "success"
    data: Optional[T] = None

# 使用示例
@router.get("/users/{user_id}")
def get_user(user_id: int):
    user = service.get_user(user_id)
    return ResponseModel(data=user)
        

前端axios拦截器统一处理这个结构,代码量直接砍半。是不是以为这样就完了?不,还有一个关于错误码的约定,建议至少约定401去登录、403无权限、422参数错误,别让前端去猜。

🌍 开发 vs 生产:别再手改baseURL了!

我见过最野的操作:每次部署前,手动把 axios baseURL localhost:8000改成线上域名,然后commit,然后……忘了改回来。😱

正确姿势:用环境变量

# frontend/.env.development
VITE_API_BASE_URL = '/api'   # 开发走代理

# frontend/.env.production
VITE_API_BASE_URL = 'https://your-api-domain.com'
// frontend/src/api/request.js
const request = axios.create({
    baseURL: import.meta.env.VITE_API_BASE_URL,
    timeout: 10000
})

后端也一样,用python-dotenv加载 .env 文件,永远不要把密钥写死在代码里

💣 再说三个容易翻车的点(都是真金白银换的教训)

⚠️ 第一个:路径拼接的斜杠

后端路由@app.get("/users"),前端请求/users/(多了一个斜杠),在nginx下可能301重定向,cookie丢了。

建议统一规则:路由末尾不加斜杠,前端请求也不加

⚠️ 第二个:请求/响应拦截器里的“循环引用”

有人在拦截器里用response.data.data取数据,但刷新token的接口又走了同一个拦截器,结果死循环。

解决方案:在白名单接口的meta里加一个标记跳过拦截器

⚠️ 第三个:FastAPI的异步陷阱 

如果你用了async def,里面却调用同步的SQLAlchemy操作,会阻塞事件循环。

要么全用def,要么用asyncio.to_thread。很多人不知道,上了生产才发现接口越跑越慢。

🧠 进阶思考:拆分vs聚合,你的项目适合哪种?

是不是以为前后端分离就一定得两个仓库、两套部署?不一定。小型项目或内部工具,可以把Vue构建后的dist文件夹放到FastAPI的static目录下,用同一个端口服务。这样省去跨域配置,部署也简单。

如果团队超过3个人,或者前后端需要独立迭代,强烈建议完全分离:后端一套API,前端单独部署到CDN或Nginx。这好比厨房和餐厅:小饭馆可以共用空间,但连锁餐厅必须分开,才能同时接单。

好了,今天就聊到这儿。上面这些配置和结构,都是我在项目里反复打磨过的,你拿过去改改就能跑起来

如果你在实战中也遇到过奇葩坑,或者对某个步骤有疑问,欢迎评论区吐槽。程序媛的时间很宝贵,但分享经验这事儿,我乐意。觉得有用的话,点个赞+关注,让更多人看到这份“避坑指南”。

💬 最后啰嗦一句:技术文章写得再好,不如你自己动手敲一遍。赶紧打开编辑器,从那个CORS配置开始吧!