Skip to main content

🔧 Monorepo 架构全解析:技术细节 + 优劣势分析

🕒 预计阅读时间:7 分钟
📌 一句话总结:Monorepo 就是“所有代码放一仓”,利于协作和统一管理,但也有一定的规模挑战。


🧠 什么是 Monorepo?

Monorepo(Mono + Repository)指多个项目(如前端、后端、库等)放在同一个 Git 仓库中统一管理的一种项目结构。相对概念是 Polyrepo,即一个项目一个仓库。

典型 Monorepo 目录结构:

my-monorepo/
├── apps/
│   ├── frontend/
│   └── backend/
├── packages/
│   ├── ui-components/
│   └── utils/
├── .gitignore
├── pnpm-workspace.yaml
└── package.json

🧩 Monorepo 的核心技术点

1. 🏗 包管理器支持(pnpm / yarn / npm)

高效包管理器是 Monorepo 的基础。主流方案如下:

包管理器 支持 Monorepo 特点
pnpm 强烈推荐,快速、节省磁盘空间、有 hoist 控制
yarn workspaces Facebook 推出,生态广
npm workspaces npm v7+ 原生支持

pnpm-workspace.yaml 示例:

packages:
  - 'apps/*'
  - 'packages/*'

2. 🧪 构建工具协同(Turborepo / Nx / Lerna)

Monorepo 涉及构建顺序与依赖,需要强大任务管理工具:

工具 特点
Turborepo Vercel 出品,基于任务图构建,支持远程缓存
Nx Angular 团队孵化,功能全面
Lerna 早期代表作,现多被 pnpm/turbo 替代

turbo.json 示例:

{
  "pipeline": {
    "build": {
      "dependsOn": ["^build"],
      "outputs": ["dist/**"]
    }
  }
}

3. 🧩 模块间依赖管理(internal packages)

在 packages/ 目录下的模块,可以通过 alias 或 workspace 引用,避免发布到 NPM:

// apps/frontend/index.ts
import { formatDate } from '@myorg/utils'

通过配置:

  • TypeScript 的 paths
  • Webpack 的 resolve.alias
  • Node.js 的 exports 或 NODE_PATH

4. ✅ CI/CD 优化(增量编译 + 缓存)

Monorepo 面临构建时间爆炸的问题,所以缓存与增量构建非常关键。

  • Turborepo 支持 remote caching
  • Nx 支持 affected 命令分析变更影响范围
  • GitHub Actions 可配合 paths 做有选择的部署

5. 📦 统一发布(Versioning)

如果需要发布多个包,可以选择:

  • 固定版本模式(Fixed/Locked):所有包同步版本
  • 独立版本模式(Independent):各自独立维护版本

可借助:


⚖️ Monorepo 的优势

✅ 优势

优点 说明
📚 统一管理 方便统一 lint、test、build、CI
👯‍♀️ 跨团队协作方便 多团队代码协同易上手
📦 共享代码更高效 不必每次改 lib 就发包
🧪 自动化测试增强 可以只测/只构建受影响模块
🚀 统一发布流程 一次性发多个包不痛苦

❌ Monorepo 的挑战和劣势

❌ 劣势

缺点 说明
🐘 仓库变大 项目变多后 clone 和构建会慢
🛠 工具链复杂 需要配置 workspace、缓存、构建器
🧠 心智负担 管理依赖和变更关系更复杂
🚫 权限细化难 很难做到 repo 级权限控制
⚠️ 版本耦合风险 所有项目捆绑升级可能影响整体稳定性

📌 适合用 Monorepo 的场景

  • 多项目同属一个业务域(如电商项目的 admin、H5、小程序)
  • 重组件、重共用逻辑的项目体系
  • 中大型团队(多人维护不同模块,需要共享代码)
  • 微前端架构(需要共享 UI、utils、通信协议等)

🚫 不适合 Monorepo 的场景

  • 跨团队/跨公司协作,权限差异大
  • 模块彼此耦合度极低
  • 仓库 CI/CD 无法支持 Monorepo 优化(如不支持缓存)

💡 小结

Monorepo 是个好东西,但需要合适的工具链、团队协作模式以及自动化支持才能发挥最大价值。不适合所有项目,但对前端工程、组件库、多平台应用等非常友好。


💻 Demo 练习建议

如果你想实践,可以动手做一个 Mini-Monorepo:

npx create-turbo@latest

或手动创建:

mkdir my-monorepo
cd my-monorepo
pnpm init
pnpm add -w typescript

然后添加:

apps/web/
packages/utils/

给 utils 写一个函数 formatDate.ts,在 web 中调用它,配合 turbo run dev 启动服务,熟悉整个运行机制。