Files

84 lines
5.0 KiB
Markdown
Raw Permalink Normal View History

2026-07-17 17:17:22 +08:00
---
kind: configuration_system
name: 前后端配置系统与环境变量管理
category: configuration_system
scope:
- '**'
source_files:
- backend/src/app.js
- backend/src/config/loadEnv.js
- backend/src/config/env.js
- backend/src/config/database.js
- backend/src/config/redis.js
- backend/src/config/logger.js
- docker-compose.yml
- frontend/.env
- frontend/.env.prod
- frontend/.env.test
- frontend/vite.config.ts
---
## 1. 系统概览
本项目采用**前后端分离 + Docker Compose 编排**的架构,配置系统围绕“环境变量优先、文件兜底”的原则组织:
- **后端(Node.js/Express**:通过 `dotenv` 从仓库根目录 `.env` 加载,Docker 部署时由 `docker-compose.yml``env_file` 注入,不覆盖已有环境变量。
- **前端(Vite**:使用 Vite 内置的 `loadEnv`,按构建模式(development / test / production)分别读取 `.env``.env.test``.env.prod`,所有 `VITE_` 前缀变量在构建期注入到 `import.meta.env`
- **容器编排**`docker-compose.yml` 通过 `env_file``environment` 为后端注入运行时配置,并通过端口映射与 Nginx 静态资源卷完成服务暴露。
## 2. 关键文件与包
| 层级 | 文件 | 作用 |
|------|------|------|
| 后端入口 | `backend/src/app.js` | 首行 `require('./config/loadEnv')` 触发 .env 加载;集中挂载中间件、路由、启动监听 |
| 环境判断 | `backend/src/config/env.js` | 基于 `APP_ENV` 导出 `isDevelopment` / `isProduction` 布尔值 |
| 环境变量加载 | `backend/src/config/loadEnv.js` | 仅当根目录存在 `.env` 时才调用 `dotenv.config`,避免覆盖容器注入的环境变量 |
| 数据库配置 | `backend/src/config/database.js` | 从 `DATABASE_*` 环境变量构造 Sequelize 实例,开发模式开启 SQL 日志 |
| Redis 缓存 | `backend/src/config/redis.js` | 懒初始化 ioredis 客户端,支持密码与多 DB 选择 |
| 日志配置 | `backend/src/config/logger.js` | winston 双传输(Console + File),固定输出到 `backend/logs/app.log` |
| 容器编排 | `docker-compose.yml` | 定义 backend/frontend 两个服务,通过 `env_file: .env` 注入后端配置,固定 `PORT=8000` |
| 前端基础配置 | `frontend/.env` | 应用标题、路由模式、代理开关等通用 Vite 变量 |
| 前端生产配置 | `frontend/.env.prod` | 指定 `VITE_SERVICE_BASE_URL=/api`(同域 Nginx 反代) |
| 前端测试配置 | `frontend/.env.test` | 指向本地后端 `http://localhost:8083/api` |
| Vite 构建脚本 | `frontend/vite.config.ts` | 通过 `loadEnv(mode, cwd)` 读取对应 `.env.*`,并注入 `base``proxy``define` 等 |
## 3. 架构与设计约定
### 3.1 后端配置加载顺序
```
进程启动 → app.js → require('./config/loadEnv')
→ dotenv.config({ path: root/.env }) // 仅当文件存在
→ 各模块直接 process.env.XXX 取值
```
- **优先级**:容器注入环境变量 > `.env` 文件默认值(`process.env.DATABASE_PASSWORD || 'root123'`)。
- **环境区分**`APP_ENV` 决定 `isDevelopment` / `isProduction`,用于控制 Sequelize SQL 日志开关等。
### 3.2 前端配置加载顺序
```
vite serve/build → loadEnv(mode, cwd)
→ development: 读取 .env + .env.development
→ test: 读取 .env + .env.test
→ production: 读取 .env + .env.prod
→ 仅 VITE_* 前缀变量注入到 import.meta.env
```
- 生产构建产物不包含源码,因此 `VITE_SERVICE_BASE_URL=/api` 通过 Nginx 反向代理到后端 `/api`,实现同源部署。
- 开发/测试环境通过 `VITE_HTTP_PROXY=Y` 配合 `createViteProxy` 将请求转发到 `http://localhost:8083`
### 3.3 容器化配置
- 后端容器内固定 `PORT=8000`,宿主机映射 `8083:8000`,与 Nginx `proxy_pass http://backend:8000` 一致。
- `extra_hosts: host.docker.internal:host-gateway` 允许容器访问宿主机 MySQL/Redis。
- 前端容器只挂载静态资源与 nginx.conf,无运行时配置。
## 4. 开发者应遵循的规则
1. **新增后端环境变量**:统一以 `DATABASE_*``REDIS_*``PORT``APP_ENV` 等大写命名,在 `backend/src/config/*.js` 中提供默认值,并在 `docker-compose.yml``env_file``environment` 中声明。
2. **不要修改 `loadEnv.js` 的加载逻辑**:它刻意只在本地存在 `.env` 时才加载,避免覆盖 Docker 注入的环境变量。
3. **新增前端环境变量**:必须以 `VITE_` 开头,放在对应环境的 `.env.*` 文件中;若需跨环境共享,放入根 `.env`
4. **生产部署**:确保 `frontend/.env.prod``VITE_SERVICE_BASE_URL` 与 Nginx 的反代路径一致(当前为 `/api`)。
5. **敏感信息**:数据库密码、Redis 密码等不要提交到版本库,使用 `docker-compose.yml``env_file` 或宿主机的环境变量注入。
6. **日志位置**:后端日志固定写入 `backend/logs/app.log`,容器内可通过 volume 持久化到宿主机 `/data/projects/source`