2026-08-26 16:20:55 +08:00

47 lines
2.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ADR-005: Monorepo 布局pnpm workspaceapps/server + apps/web + packages/shared
## Status: Accepted (2026-08-26)
## Background
后端Express与前端Vue3同用 TypeScript且有大量共享的领域类型由 zod schema 经 `z.infer` 产出、zod 数据 schema、统一响应 `ApiResponse<T>`、错误码、枚举。若前后端各自复制一份类型定义,一旦模型变更会出现「同一模型多处漂移」,违背 spec-as-contract契约应单点可寻址
## Decision
采用 **pnpm workspace 单仓多包**
```
gwy-exam/
├── pnpm-workspace.yaml
├── package.json # 仅脚本 + workspace不装业务依赖
├── tsconfig.base.json # 共享 strict 编译基座
├── apps/
│ ├── server/ # Express 5 + TS + ESM
│ └── web/ # Vue3 + Vite + TS
└── packages/
└── shared/ # 领域类型 + zod schema + ApiResponse + 枚举 + 常量
```
类型契约、zod schema、`ApiResponse<T>`、错误码联合全部放 `packages/shared``apps/server``apps/web` 通过 workspace 引用共享。
### 为什么选 monorepo 而非独立仓
1. 前后端同 JS/TS`packages/shared` 是天然共享层,独立仓需额外发布/维护两份。
2. 契约类型单点维护防漂移spec-as-contract契约可寻址、可审计
3. 一次 `pnpm install`、一次 CI开发与验收路径单一。
### 分层依赖(对照 code-organization.md
- `apps/server` 依赖 `packages/shared`(向下)。
- `apps/web` 依赖 `packages/shared`(向下)。
- `packages/shared` **不依赖任何 app**,保持纯净、可被任何一方 import 而无环。
## Consequences
- 正面:类型单一来源、契约一致、前后端并行开发不踩、一次安装。
- 负面:单仓体积稍大;`packages/shared` 须保持无业务、无 app 依赖(否则环),需纪律约束。
- 权衡个人工具规模下monorepo 的成本(配置 pnpm workspace + 共享 tsconfig远低于收益类型一致性。若未来拆出多应用可无损演进。
## Related ADRs
- ADR-001Express/ ADR-002Vue+Vite
- ADR-004全 TS strict — 与 shared 类型强绑定)
- ADR-006垂直切片 — shared 作为单一契约源的承载层)