Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ AI_API_KEY=your-ai-api-key
# ── 服务配置 ──
WINDUP_HOST=127.0.0.1
WINDUP_PORT=8000
# 前端构建期写入的后端地址。默认相对路径,由宿主机 nginx 反代给 backend;
# 只有在前端要指向外部后端时才改成完整 URL,那时后端需同步配 WINDUP_CORS_ORIGINS
VITE_API_BASE_URL=/api
# 跨域来源(逗号分隔,默认覆盖 localhost:5173/3000)
WINDUP_CORS_ORIGINS=
# 跨域正则匹配(默认允许 *.vercel.app)
Expand Down
19 changes: 19 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,25 @@ services:
networks:
- windup-net

# ── 前端静态产物构建任务 ──
frontend:
build:
context: ./frontend
dockerfile: Dockerfile
args:
# 构建期烘进产物的后端地址,运行期改不动,所以放在 build.args 而非
# environment。默认相对路径 → 与页面同源 → 不产生跨域,后端不必配来源白名单。
VITE_API_BASE_URL: ${VITE_API_BASE_URL:-/api}
container_name: windup-frontend
restart: "no"
depends_on:
- backend
volumes:
# 构建命令直接写入宿主机 nginx 的站点目录;容器退出后产物仍保留。
- /var/www/react-windup:/var/www/react-windup
networks:
- windup-net

networks:
windup-net:
driver: bridge
Expand Down
15 changes: 15 additions & 0 deletions frontend/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# 构建上下文排除项:本地 node_modules 与 dist 加起来数百 MB,
# 全量传给 daemon 会让每次构建白等一分钟,且容器内会重新装依赖、重新构建。
node_modules
dist
dist-ssr

# 本地环境变量文件不进镜像;后端地址由 Dockerfile 的 build arg 传入。
.env
.env.*

.vercel
.git
.gitignore
.DS_Store
*.log
28 changes: 28 additions & 0 deletions frontend/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# ── 前端构建容器 ─────────────────────────────────────────────────────
# 容器只负责生成静态产物,宿主机 nginx 直接读取挂载目录。
# Node 版本跟 frontend-ci.yml 对齐,避免 CI 过了、镜像里构建结果不同
FROM node:24-alpine

# 国内网络:走镜像源,与 backend/Dockerfile 换阿里 pypi 源同因
ENV NPM_CONFIG_REGISTRY=https://registry.npmmirror.com

WORKDIR /app

# 先只拷依赖清单,命中 Docker layer cache —— 改源码不触发重装依赖
COPY package.json package-lock.json ./
RUN npm ci

COPY . .

# VITE_ 前缀的变量在 vite build 时就被烘进 dist,运行期再往容器注环境变量对
# 已构建产物无效 —— 这是前端和 backend 在配置方式上唯一的实质差别。
# 默认值 /api 是相对路径:浏览器请求与页面同源,由宿主机 nginx 转发给后端,
# 构建镜像因此不与任何域名绑定,同一份产物可直接换环境跑。
# 若某个环境确实要指向外部后端,构建时传 --build-arg VITE_API_BASE_URL=https://…,
# 但那样后端必须同步配 WINDUP_CORS_ORIGINS,否则浏览器预检就被拦死。
ARG VITE_API_BASE_URL=/api
ENV VITE_API_BASE_URL=$VITE_API_BASE_URL

# build 脚本是 tsc -b && vite build,类型不过直接构建失败。产物直接写进
# Compose 挂载的宿主机目录;构建完成后进程退出,不启动常驻服务。
CMD ["npm", "run", "build", "--", "--outDir", "/var/www/react-windup", "--emptyOutDir"]
16 changes: 16 additions & 0 deletions frontend/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,22 @@ npm run build # 构建

CI 按上面顺序全跑一遍。

## 容器构建与宿主机部署

服务器由宿主机 nginx 提供静态资源并反代 `/api`。前端容器只构建产物:

```bash
cp .env.example .env
sudo mkdir -p /var/www/react-windup
docker compose up -d --build frontend
```

构建命令会清空专用站点目录 `/var/www/react-windup`,再把文件直接写入宿主机;完成后容器正常退出,没有端口映射,也不常驻。宿主机 nginx 的站点根目录需指向该目录,并负责 SPA 回退与 `/api` 反代。之后每次更新仍执行上面的 Compose 命令,nginx 会直接读取新产物。

`VITE_API_BASE_URL` 是构建期变量,`vite build` 时就烘进产物,运行期给容器注环境变量无效。默认取 `/api` 走宿主机反代;确实要指向外部后端时,构建时传 `--build-arg VITE_API_BASE_URL=https://…`,同时后端得配 `WINDUP_CORS_ORIGINS`。

Vercel 部署路径不受影响,`vercel.json` 照旧。

## 结构

`ProjectApis` 与 `CharacterApis` 负责业务 DTO 映射。项目中心、项目工作区、资产库与角色详情已接入 PR #75 的真实接口;测试数据只存在于测试环境的 HTTP 替身中。
Expand Down