部署前准备工作-fastapi解决跨域

后端添加 CORS 支持

遇到的问题:

  • ❌ CORS 跨域错误

解决方案(main.py):

python

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

# ✅ 添加 CORS 中间件
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)

@app.get("/api/videos")
async def get_videos_api():
# 你的代码...

解决自动识别开发环境/生产环境

🎯 核心原理总结

最关键的三个部分:

1️⃣ 环境文件(项目根目录)

bash

1
2
.env.development     # 开发环境
.env.production # 生产环境

env

1
VUE_APP_API_BASE_URL=http://localhost:8000

2️⃣ Axios 实例(src/utils/request.js)

javascript

1
2
3
const request = axios.create({
baseURL: process.env.VUE_APP_API_BASE_URL // ← 这是核心!
})

3️⃣ 运行命令

bash

1
2
3
4
5
6
7
8
9
10
11
12
13
14
npm run serve  → 自动用开发环境(localhost:8000)
npm run build → 自动用生产环境(服务器地址)

具体流程
你写的代码:
baseURL: process.env.VUE_APP_API_BASE_URL

↓ (编译时)

开发环境编译后:
baseURL: "http://localhost:8000"

生产环境编译后:
baseURL: "http://120.77.237.223:8000"

改造 HotVideosView 等vue组件 做了什么?

只做了 4 件事:

  1. 改导入axiosrequest
  2. 删数据:删除 apiBaseUrl: 'http://...'
  3. 改调用axios.get(完整URL)request.get(相对路径)
  4. 改数据response.data → 直接用 data

为什么这样改有效?

javascript

1
2
3
4
5
6
7
8
9
// request 实例已经配置了 baseURL
const request = axios.create({
baseURL: process.env.VUE_APP_API_BASE_URL // 自动读取环境
})

// 响应拦截器简化了数据提取
request.interceptors.response.use(
response => response.data // 直接返回 data 部分
)

你以后开发新功能的标准模板:

javascript

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<script>
import request from '@/utils/request' // 1. 导入

export default {
data() {
return {
data: [],
loading: false
// 2. 不需要 apiBaseUrl
}
},

methods: {
async loadData() {
this.loading = true
try {
// 3. 只写相对路径
const data = await request.get('/api/xxx')
this.data = data // 4. 直接用 data
} catch (err) {
console.error(err)
} finally {
this.loading = false
}
}
}
}
</script>


主要改动:

  1. ✅ 导入 request 实例替代 axios
  2. ✅ 移除了 apiBaseUrl 数据项
  3. ✅ 使用 request.get('/api/hot-videos') 替代完整 URL
  4. ✅ 简化了错误处理
  5. data 直接是响应数据(注意数据结构从 response.data 变成了 data

现在所有三个页面都统一使用 axios 实例:

  • HomeView - 首页推荐
  • HotVideosView - 热门排行榜
  • NostalgiaVideosView - 怀旧视频收藏夹

统一的优势:

  • 🚀 自动识别开发/生产环境
  • 🔧 统一的错误处理
  • 📝 统一的日志记录
  • 🎯 只需维护一个配置文件-> request.js ↓
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import axios from 'axios'

// 根据环境自动切换
const baseURL = process.env.VUE_APP_API_BASE_URL || 'http://localhost:8000'

const request = axios.create({
baseURL: baseURL,
timeout: 10000,
headers: {
'Content-Type': 'application/json'
}
})

// 请求拦截器
request.interceptors.request.use(
config => {
console.log('请求URL:', config.baseURL + config.url)
return config
},
error => {
return Promise.reject(error)
}
)

// 响应拦截器
request.interceptors.response.use(
response => {
return response.data
},
error => {
console.error('请求失败:', error)
return Promise.reject(error)
}
)

export default request

🎯 简单总结 request.js 的作用

把它想象成一个"请求助手":

1. 基础配置(创建实例)

javascript

1
2
3
4
5
const request = axios.create({
baseURL: 'http://localhost:8000', // 所有请求的前缀
timeout: 10000, // 10秒超时
headers: { 'Content-Type': 'application/json' }
})

2. 请求前处理(请求拦截器)

javascript

1
2
3
4
5
request.interceptors.request.use(config => {
console.log('发送请求:', config.url) // 打印日志
// 可以添加 token
return config // 必须返回!
})

3. 响应后处理(响应拦截器)

javascript

1
2
3
request.interceptors.response.use(response => {
return response.data // 直接返回数据部分,简化使用
})

4. 完整请求流程

1
组件调用 → 请求拦截器 → 发送请求 → 服务器响应 → 响应拦截器 → 组件接收

核心好处:写一次配置,所有地方自动生效!

🚀 FastAPI + Vue 项目 Docker 部署完整总结

📋 项目概述

项目结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
animeV/
├── main.py # FastAPI 后端
├── bill.py
├── requirements.txt # Python 依赖
├── Dockerfile # 后端 Docker 配置
├── docker-compose.yml # 容器编排配置
├── .claude/
└── animeshow/ # Vue 前端
├── src/
├── dist/ # 构建产物
├── package.json
├── Dockerfile # 前端 Docker 配置
└── nginx.conf # Nginx 配置

🎯 部署架构

1
2
3
4
5
6
7
8
浏览器

http://120.77.237.223:80 (Nginx - 前端)

├─ / → Vue 静态文件
└─ /api/ → 代理到后端

http://backend:8000 (FastAPI)

📝 完整部署过程

第一阶段:准备工作

1. 本地开发环境

bash

1
2
3
4
# 项目目录
D:\PycharmProjects\animeV\
├── main.py # FastAPI 后端
└── animeshow/ # Vue 前端

2. 安装 Docker 和必要工具

bash

1
2
3
4
5
6
7
8
# 服务器端
curl -fsSL https://get.docker.com | bash
systemctl start docker
systemctl enable docker

# 安装 Docker Compose
curl -L "https://github.com/docker/compose/releases/download/v2.20.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose

第二阶段:创建 Docker 配置文件

1. 后端 Dockerfile

遇到的问题:

  • ❌ pip 安装超时
  • ❌ 缺少 bilibili-api-python 依赖
  • ❌ 网络问题

最终配置:

dockerfile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
FROM python:3.9-slim

WORKDIR /app

COPY requirements.txt .

# 使用国内镜像源
RUN pip install --no-cache-dir -r requirements.txt \
-i https://pypi.tuna.tsinghua.edu.cn/simple \
--trusted-host pypi.tuna.tsinghua.edu.cn

COPY . .

EXPOSE 8000

# 添加 --reload 支持热重载
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000", "--reload"]

2. 后端 requirements.txt

遇到的问题:

  • ❌ 初始只有 fastapi 和 uvicorn
  • ❌ 缺少 bilibili-api-python 导致 ModuleNotFoundError

最终配置:

txt

1
2
3
4
5
6
7
fastapi
uvicorn[standard]
bilibili-api-python
httpx
aiohttp
pydantic
python-multipart

3. 后端添加 CORS 支持

遇到的问题:

  • ❌ CORS 跨域错误

解决方案(main.py):

python

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

# ✅ 添加 CORS 中间件
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)

@app.get("/api/videos")
async def get_videos_api():
# 你的代码...

4. 前端 Dockerfile

遇到的问题:

  • ❌ npm 镜像源超时
  • ❌ package-lock.json 锁定了错误的镜像源
  • ❌ vue-cli-service 权限问题
  • ❌ 构建超时

解决方案:本地构建 + 服务器部署

dockerfile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
FROM nginx:alpine

# 直接复制本地构建好的 dist
COPY dist /usr/share/nginx/html

# Nginx 配置
RUN echo 'server { \
listen 80; \
location / { \
root /usr/share/nginx/html; \
index index.html; \
try_files $uri $uri/ /index.html; \
} \
location /api/ { \
proxy_pass http://backend:8000/api/; \
proxy_set_header Host $host; \
proxy_set_header X-Real-IP $remote_addr; \
} \
}' > /etc/nginx/conf.d/default.conf

EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

5. 前端 nginx.conf

nginx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
server {
listen 80;
server_name localhost;

# 前端静态文件
location / {
root /usr/share/nginx/html;
index index.html;
try_files $uri $uri/ /index.html;
}

# 代理后端 API
location /api/ {
proxy_pass http://backend:8000/api/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}

6. docker-compose.yml

最终配置:

yaml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
services:
backend:
build: .
container_name: anime_backend
ports:
- "8000:8000"
volumes:
- .:/app # 挂载代码支持热重载
environment:
- PYTHONUNBUFFERED=1
command: uvicorn main:app --host 0.0.0.0 --port 8000 --reload
restart: unless-stopped

frontend:
build: ./animeshow
container_name: anime_frontend
ports:
- "80:80"
depends_on:
- backend
restart: unless-stopped

第三阶段:前端配置

1. API 地址配置问题

遇到的问题:

  • ❌ 硬编码 localhost:8000
  • ❌ 多处配置不一致

最终方案:环境自动判断

main.js:

javascript

1
2
3
4
5
6
7
8
9
10
11
12
import axios from 'axios'

// ✅ 开发环境用 localhost,生产环境用服务器地址
const isDevelopment = process.env.NODE_ENV === 'development'
axios.defaults.baseURL = isDevelopment
? 'http://localhost:8000'
: 'http://120.77.237.223:8000'

axios.defaults.timeout = 10000

console.log('当前环境:', process.env.NODE_ENV)
console.log('API 地址:', axios.defaults.baseURL)

HomeView.vue:

javascript

1
2
3
4
5
6
7
8
9
10
11
12
13
14
data() {
return {
videos: [],
loading: false,
error: null,
apiBaseUrl: '' // 空字符串,使用 axios 全局配置
}
},
methods: {
async loadVideos() {
const response = await axios.get('/api/videos') // 相对路径
// ...
}
}

2. 本地开发代理配置

vue.config.js:

javascript

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const { defineConfig } = require('@vue/cli-service')

module.exports = defineConfig({
transpileDependencies: true,

devServer: {
port: 8080,
proxy: {
'/api': {
target: 'http://localhost:8000',
changeOrigin: true
}
}
}
})

第四阶段:上传和部署

1. 本地构建前端

bash

1
2
3
4
5
6
7
8
# Windows 本地
cd D:\PycharmProjects\animeV\animeshow

# 删除旧构建
rmdir /s /q dist

# 重新构建
npm run build

2. 上传文件到服务器

使用 WinSCP:

1
2
3
4
5
6
7
8
9
10
11
12
13
连接信息:
Host: 120.77.237.223
Port: 22
User: root

上传内容:
本地 D:\PycharmProjects\animeV\
→ 服务器 /root/animeV/

特别注意:
✅ 上传 animeshow/dist 文件夹
✅ 上传所有 .py 文件
✅ 上传 Dockerfile 和 docker-compose.yml

3. 服务器构建和运行

bash

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
ssh root@120.77.237.223
cd /root/animeV

# 停止旧容器
docker compose down

# 清理(可选)
docker system prune -f

# 重新构建
docker compose build --no-cache

# 启动容器
docker compose up -d

# 查看日志
docker compose logs -f

第五阶段:网络配置

1. 阿里云安全组配置

开放端口:

1
2
3
4
端口协议用途
22TCPSSH
80TCP前端(Nginx)
8000TCP后端(FastAPI)

2. 服务器防火墙

bash

1
2
3
4
5
6
7
# 开放端口
firewall-cmd --permanent --add-port=80/tcp
firewall-cmd --permanent --add-port=8000/tcp
firewall-cmd --reload

# 或关闭防火墙(测试用)
systemctl stop firewalld

指定地址路由部署->xxx.com/bili

解决方案 1: 修改 vue.config.js

assetsDir 去掉或改为空字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// D:\PycharmProjects\animeV\animeshow\vue.config.js
const { defineConfig } = require('@vue/cli-service')

module.exports = defineConfig({
transpileDependencies: true,

publicPath: process.env.NODE_ENV === 'production' ? '/bili/' : '/',

outputDir: 'dist',
// ✅ 去掉这行或改为空
// assetsDir: 'static', // <-- 删除这行

devServer: {
port: 8080,
proxy: {
'/api': {
target: 'http://localhost:8000',
changeOrigin: true
}
}
}
})

配置nginx

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
server {
listen 80;
server_name _;

location /bili/ {
alias /usr/share/nginx/html/bili/;
index index.html;
try_files $uri $uri/ /bili/index.html;
}

location /bili {
return 301 /bili/;
}

location /api/ {
proxy_pass http://backend:8000/api/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}

location = / {
return 301 /bili/;
}
}

完整部署流程

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 1. 确保 vue.config.js 已修改(去掉 assetsDir)
# 2. 重新构建前端
npm run build

# 3. 检查 dist 目录
ls -la dist/
ls -la dist/js/
ls -la dist/css/

# 4. 清理旧容器和镜像
docker stop vue-bili-container 2>/dev/null || true
docker rm vue-bili-container 2>/dev/null || true
docker rmi vue-bili 2>/dev/null || true

# 5. 构建新镜像
docker build -t vue-bili .

# 6. 运行容器
docker run -d --name vue-bili-container -p 80:80 vue-bili

# 7. 验证
docker ps | grep vue-bili
docker logs vue-bili-container