准备部署

This commit is contained in:
AgentLabCn
2026-06-15 21:21:20 +08:00
parent 4167714149
commit 6c22cf9ef7
17 changed files with 898 additions and 2 deletions
+23
View File
@@ -0,0 +1,23 @@
# 排除无需进入构建上下文的文件
node_modules/
dist/
# 环境变量(含密钥/本地配置,不应进入镜像)—— 与 backend/.dockerignore 保持一致
.env
.env.*
# 日志
*.log
npm-debug.log*
yarn-debug.log*
pnpm-debug.log*
# 版本控制与编辑器
.git/
.gitignore
.vscode/
.idea/
# Dockerfile 本身
Dockerfile
Dockerfile.prod
+4
View File
@@ -0,0 +1,4 @@
# 开发环境前端变量(vite dev 在 development 模式下自动加载此文件)
# 生产构建(vite build)不会读取此文件 —— 生产环境前端使用页面同源地址。
VITE_API_BASE_URL=http://localhost:8000
VITE_WS_BASE_URL=ws://localhost:8000
+41
View File
@@ -0,0 +1,41 @@
# ============================================================
# 青叶 —— 生产环境前端镜像(多阶段构建)
# Stage 1: Node 构建 Vite 生产包
# Stage 2: Nginx 提供静态文件 + SPA 路由回退
# ------------------------------------------------------------
# 构建「域名无关」:不设置任何 VITE_* 变量。前端代码在没有 VITE_API_BASE_URL /
# VITE_WS_BASE_URL 时,会自动使用页面同源地址(API 走相对路径 /api/v1
# WebSocket 走 wss://<当前域名>)。因此同一份镜像可部署到任意域名。
# ============================================================
# ===== Stage 1: 构建 =====
FROM node:20-alpine AS builder
WORKDIR /app
# 复制依赖描述(package-lock.json 可选 —— 仓库未提交锁文件,用 npm install
COPY package.json package-lock.json* ./
# 安装依赖(使用 npm 官方源)
RUN npm install
# 复制源码(frontend/.dockerignore 已排除 node_modules / dist / .env 等)
COPY . .
# 直接调用 vite build,跳过 vue-tsc 类型检查
# (避免仓库中既有的类型错误阻断生产部署;类型检查请在 CI / 发布前单独执行)
# 如需严格的类型门禁,可改为 `npm run build`。
RUN npx vite build
# ===== Stage 2: 运行(Nginx 静态服务) =====
FROM nginx:alpine
# 复制构建产物
COPY --from=builder /app/dist /usr/share/nginx/html
# 复制 SPA 专用 Nginx 配置(createWebHistory 需要 try_files 回退)
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
+28
View File
@@ -0,0 +1,28 @@
# 青叶前端容器 Nginx 配置(提供 SPA 静态文件)
# 仅负责静态资源与前端路由回退;API / WebSocket / 上传文件由「宿主机 Nginx」转发到后端。
server {
listen 80;
server_name _;
root /usr/share/nginx/html;
index index.html;
# gzip 压缩
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_types text/plain text/css application/json application/javascript application/xml text/xml application/xml+rss text/javascript image/svg+xml;
# SPA 路由回退:Vue Router 使用 createWebHistoryHTML5 history 模式),
# 刷新 /chat、/moments 等前端路由时需回退到 index.html
location / {
try_files $uri $uri/ /index.html;
}
# 静态资源长缓存(Vite 产物带 hash 文件名,可安全强缓存)
location ~* \.(?:js|css|woff2?|ttf|eot|png|jpg|jpeg|gif|ico|svg)$ {
expires 30d;
add_header Cache-Control "public, immutable";
access_log off;
}
}
+4 -1
View File
@@ -1,6 +1,9 @@
import axios, { type AxiosInstance } from 'axios'
const API_BASE = import.meta.env.VITE_API_BASE_URL || 'http://localhost:8000'
// 域名无关:未显式配置 VITE_API_BASE_URL 时使用「同源相对地址」,
// 即请求发往当前页面所在的域名(生产环境与前端同源)。
// 开发时由 frontend/.env.development 提供 http://localhost:8000。
const API_BASE = import.meta.env.VITE_API_BASE_URL || ''
const api: AxiosInstance = axios.create({
baseURL: `${API_BASE}/api/v1`,
+5 -1
View File
@@ -2,7 +2,11 @@ import { ref } from 'vue'
import { useAuthStore } from '@/stores/auth'
import { useChatStore } from '@/stores/chat'
const WS_BASE = import.meta.env.VITE_WS_BASE_URL || 'ws://localhost:8000'
// 域名无关:未显式配置时根据当前页面协议自动推导(https→wss, http→ws)。
// 开发时由 frontend/.env.development 提供 ws://localhost:8000。
const WS_BASE =
import.meta.env.VITE_WS_BASE_URL ||
`${window.location.protocol === 'https:' ? 'wss:' : 'ws:'}//${window.location.host}`
let ws: WebSocket | null = null
let reconnectAttempts = 0