在 AI 时代重新思考架构 — 第 1 部分:仓库管理
Source: Dev.to
请提供您希望翻译的正文内容,我将为您翻译成简体中文并保持原有的格式、Markdown 语法以及技术术语不变。
仓库管理 – 为什么单体仓库是合理的
关于 AI 如何快速加速原型制作的内容层出不穷——但中期可维护性同样值得关注。
(如果这篇文章只是一次性发布,提前致歉。)
我的前置结论
选择单体仓库。
什么是 Monorepo?
Monorepo 是在单一仓库中管理多个应用的实践。“多个应用”可以指以下任意情况:
- 前端和后端共存
- Service A 与 Service B 的全栈应用并排
- 应用代码与共享库共存
关于微服务的简短说明
虽然在微服务的语境中有时会讨论 Monorepo,但我没有将两者结合的实际经验,所以此处不作讨论。我的直觉是,要充分利用 Monorepo,需要保持技术栈相对统一——这在某种程度上与微服务的目标相冲突。我描述的 Monorepo 风格可能并不适合微服务。
Source: …
实用答案:Turborepo
Turborepo 已经成为 TypeScript 项目中 monorepo 设置的事实标准。虽然它在技术上定位为通用构建工具,但在实际使用中,当你采用 monorepo(或想要更智能的构建缓存)时,通常会选择它。
代表性目录结构(Web 前端 + 后端)
my-turborepo/
├── apps/
│ ├── web/ # 前端应用(例如 Next.js)
│ │ ├── src/
│ │ ├── package.json
│ │ └── tsconfig.json
│ └── api/ # 后端应用(例如 Hono、Express)
│ ├── src/
│ ├── package.json
│ └── tsconfig.json
├── packages/
│ ├── ui/ # 共享 UI 组件库
│ │ ├── src/
│ │ ├── package.json
│ │ └── tsconfig.json
│ ├── tsconfig/ # 共享 TypeScript 配置
│ │ ├── base.json
│ │ ├── nextjs.json
│ │ └── package.json
│ └── utils/ # 共享工具函数
│ ├── src/
│ ├── package.json
│ └── tsconfig.json
├── .claude/
│ ├── CLAUDE.md
│ └── skills/
├── .codex/
│ └── skills/
├── turbo.json
├── biome.json
├── package.json
├── pnpm-workspace.yaml
└── tsconfig.jsonapps/保存各个独立的应用。packages/保存共享代码——工具函数、UI 组件以及像tsconfig这样的配置文件。
你可以在没有 Turborepo 的情况下复制此布局,但 Turborepo 带来的实际价值在于:
- 读取每个
package.json。 - 批量或并行运行构建和测试。
- 智能处理构建缓存——当构建时间开始成为瓶颈时,这一点优势尤为明显。
AI 时代的知识库管理
知识库只有在被实际引用时才有价值。要便于引用,知识必须彼此紧密相连。
使用 monorepo,克隆单个 GitHub 仓库即可在一个地方获取所有内容:
- 应用代码
- 开发文档
- 代理技能(例如 Claude、Codex)
你可以想办法让 AI 识别多个仓库属于同一个项目,但何必费心?monorepo 免费为你提供了这种一致性。
常见异议与重新框定
“前端和后端只需要通过 API 合约进行通信——混合它们的上下文是没有必要的。”
在 AI 辅助编码的时代,优势来自能够让你看到全局并快速迭代的架构——而不是严格的上下文分离。
当 Monorepo 发光(尤其在 AI 时代开发中)
你的后端使用 TypeScript 编写
- 混合技术栈(例如,前端使用 TypeScript,后端使用 Python)在技术上可以是 monorepo,但共享的
packages/会变成仅前端使用,价值被削弱。 - 你还需要为两种不同的语言管理 lint、格式化和工具链。
- 注意: Turborepo 围绕 TypeScript(以及
package.json作为主要配置单元)构建,因此将技术栈统一到 TypeScript 是阻力最小的路径。
- 混合技术栈(例如,前端使用 TypeScript,后端使用 Python)在技术上可以是 monorepo,但共享的
你的审查流程已适配 AI 辅助开发
- 在使用 AI 编码的 monorepo 中,实现单个功能往往意味着 AI 同时编写前端 和 后端代码,一次性完成。Pull request 自然会体现端到端的实现。
- 如果仍然坚持 AI 时代前的审查仪式,人类就会成为瓶颈。至少,需要整合 AI 辅助的代码审查;更广泛地重新思考 PR 工作流也是值得考虑的。
真实案例:Chronock
我的应用 Chronock 采用 monorepo 结构,使用 TypeScript 构建全栈。
chronock/
├── apps/
│ ├── chronock-app/ # Frontend (React + TanStack Start)
│ ├── chronock-backend/ # Backend (Bun + Connect RPC)
│ ├── chronock-book/ # Booking page (React + TanStack Start)
│ └── chronock-www/ # Marketing site (Astro)
│
├── packages/
│ ├── contract/ # Proto definitions & generated code
│ ├── i18n/ # Internationalization utilities
│ └── typescript-config/ # Shared TypeScript config
│
├── specs/ # Product specifications
│
├── .claude/
│ ├── CLAUDE.md
│ └── skills/
├── .codex/
│ └── skills/
├── biome.jsonc # Linter / Formatter config
├── bunfig.toml # Bun config
├── docker-compose.local.yml
├── package.json
└── turbo.json # Turborepo config值得关注的几点
- 营销站点(Astro)与主应用一起位于 monorepo 中,使整个产品——包括面向公众的站点——拥有唯一的真相来源。
- 共享的合约、i18n 工具以及 TypeScript 配置集中在
packages/,从而减少重复。 - 规格说明和 AI 代理技能定义(
.claude/、.codex/)紧邻其描述的代码,知识库可即时访问。
TL;DR
- Monorepos 提供代码、文档和 AI‑agent 技能的唯一真实来源。
- Turborepo 是面向 TypeScript 为中心的 monorepos 的首选工具,提供并行构建、智能缓存和统一工作流。
- 将你的技术栈对齐到 TypeScript,并调整你的 review process 以适应 AI 辅助开发,从而获得最大的收益。
敬请期待下一篇,我们将深入探讨 AI‑first monorepos 的版本控制策略和 CI/CD 流水线。
概览
这使得诸如 “在网站上反映新功能信息” 或 “检查最新实现与着陆页文案之间的不一致性” 之类的任务,自然地可以交给 AI 代理处理。
前端 ↔ 后端 通信
- 使用 Connect RPC(Protocol Buffers)。
.proto定义文件位于packages/contract,这使得在单一位置管理接口定义并为前端和后端生成代码变得无缝。
仓库结构
- 产品规格 和 代理技能 位于同一个仓库。
- 这种集中化使得编写代理更加高效——它们拥有所需的上下文,无需跨仓库跳转。
摘要
AI 时代的架构选择
- 将上下文集中在单体仓库中,并将其视为活的知识库。
- 将技术栈统一到 TypeScript 上——它在多方面都有回报。
- Pull‑request 问题不会自行解决;它需要专门的解决方案。
第一部分完结。