ADR-0002 · 前后端拆成两个独立仓库¶
- 状态:accepted
- 日期:2026-08-01
背景(Context)¶
旧 jobhunter 是 npm workspaces 单体仓库(apps/mobile + server + packages/shared)。
在最初讨论"把 Node 后端换成 Python"时,我曾建议保持 monorepo,理由是前后端强耦合、契约同步方便。但用户提出了不同的出发点:
"我希望它能前端后端分开,因为未来可能会在上面做拓展。我觉得如果把它分成两个 repository 的话,可能更符合行业的 best practice。"
同时,后端换成 Python 这一事实改变了 monorepo 的核心收益:
- npm workspaces 管不了 Python 依赖,
npm install装不了 FastAPI packages/shared是 TypeScript 类型包,Python 无法 import——"共享类型单一事实源"这个 monorepo 最大卖点直接失效
也就是说,语言一分家,monorepo 就只剩"目录挨在一起"这点心理便利了。
决策(Decision)¶
拆成两个独立仓库:
| 仓库 | 技术栈 | 职责 |
|---|---|---|
alfred-api |
Python / FastAPI / PostgreSQL | 数据、AI 解析、Skills、提醒 |
alfred-web |
TypeScript / Taro / React | 小程序 + H5 + App 三端 |
契约对齐方式:后端 FastAPI 自动产出 openapi.json → 前端用 openapi-typescript 生成 schema.d.ts。
这比手写共享类型包更强:后端改字段,前端重新生成后 TypeScript 立刻报错,漂移无处可藏。
理由与代价(Consequences)¶
得到
- 两套语言的依赖、lint、CI、测试互不干扰
- 独立部署:后端上服务器/容器,前端发小程序/静态站,各自节奏
- 后端可以被别的客户端复用(CLI、自动化脚本、未来的 AI agent),不被前端仓库绑架
- 契约由 OpenAPI 机器生成,比人工维护的类型包更可靠
代价
- 跨仓库改动要开两个 PR(改接口 + 改调用)
- 需要一条约定:后端先合并、前端再重新生成类型
- 本地开发要同时开两个终端
缓解:前端提供 npm run sync:api 一键拉取并生成类型;接口变更在 API.md 与 CHANGELOG 里显式记录。
备选方案(Alternatives)¶
| 方案 | 为何不选 |
|---|---|
| 保持 monorepo(Python + TS 混装) | 跨语言 monorepo 需要 Nx/Bazel/Turborepo 之类的多语言编排,对个人项目是纯负担;且共享类型收益已因换语言而消失 |
| Monorepo + git submodule | submodule 的心智负担远大于两个平级仓库 |
| 三仓库(api / web / contracts) | 契约已由 OpenAPI 自动生成,单独开一个 contracts 仓库属于过度设计 |