为什么我们切换到 Monorepo

为什么我们切换到 Monorepo

• 2 分钟阅读

我们刚刚完成了一次重大基础设施升级:从独立代码库迁移到统一的 monorepo 架构。

为什么要改变?

Brandmine 包含两个主要应用:

  • Hugo 静态网站 (brandmine.ai) - 我们的公开内容平台
  • Hub 内部应用 (hub.brandmine.ai) - CRM、交易管道、故事管理

以前,它们位于独立的代码库中。每次共享更新都意味着重复工作——复制 TypeScript 类型、配置文件、同步数据结构。

问题:进行一个简单的模式更改需要在 2 个代码库中编辑 6+ 个文件,跟踪 2 个独立的部署,并希望没有任何内容失去同步。

我们构建了什么

我们的 monorepo 使用专为此场景设计的现代工具:

1. 统一工作区 (pnpm)

单个 pnpm install 命令即可安装两个应用的所有依赖项。不再需要在代码库之间跳转运行设置脚本。

2. 共享包

我们创建了 4 个供两个应用使用的内部包:

  • @brandmine/shared-types - TypeScript 接口的单一真实来源
  • @brandmine/typescript-config - 所有项目的一致 tsconfig 配置
  • @brandmine/prettier-config - 统一的代码格式化
  • @brandmine/eslint-config - 共享的代码检查规则

结果:更改一次类型定义,两个应用立即获得更新。

3. 智能构建系统 (Turborepo)

Turborepo 添加了缓存和依赖感知的任务执行:

  • 首次构建:11.4 秒
  • 缓存构建:204 毫秒(快 98%,提速 55 倍)
  • 并行开发服务器:同时启动 Hugo 和 Hub

缓存命中时的「FULL TURBO」消息令人格外满意。

实际影响

Monorepo 之前

# 终端 1
cd brandmine-hugo
npm install
hugo server

# 终端 2
cd brandmine-hub
npm install
npm run dev

# 进行模式更改
# → 编辑 hugo/data/schema.json
# → 复制到 hub/src/types/schema.ts
# → 手动保持同步
# → 希望没有遗漏任何内容

Monorepo 之后

# 单个终端
pnpm dev              # 两个应用都在运行
pnpm build            # 两个应用都已构建(带缓存)

# 进行模式更改
# → 编辑 packages/shared-types/index.ts
# → 两个应用自动更新
# → 类型安全得到保证

技术细节

5 阶段迁移

  1. ✅ 创建共享类型包
  2. ✅ 切换到 pnpm workspaces
  3. ✅ 重构为 apps/packages/ 布局
  4. ✅ 构建共享配置包
  5. ✅ 集成 Turborepo 缓存

磁盘空间:通过消除重复依赖项节省了约 500MB(减少 40-50%)。

零停机:所有迁移都在不影响生产部署的情况下进行。Cloudflare Pages 构建无缝适配。

这带来了什么

更轻松的 Hugo ↔ Hub 数据同步

我们的同步脚本(sync-to-supabase.jssync-from-supabase.js)现在直接导入共享类型。不再需要脆弱的基于字符串的验证。

自信的重构

TypeScript 知道两个应用中的所有使用情况。重命名字段?编译器会显示需要更新的每个位置。

更快的入职

新开发人员克隆一个代码库,运行 pnpm install,就可以开始了。不再有「我需要哪个代码库?」的困惑。

经验教训

过滤器名称很重要

Turborepo 需要精确的包名称(@brandmine/hugo 而不是 hugo)。当 Cloudflare 构建失败时,我们吃了苦头。现在我们先在本地测试过滤器名称。

Monorepo 的 Gitignore 模式

根级别的模式(/public/)不适用于子目录(apps/hugo/public/)。我们立即修复了这个问题,并删除了 1000+ 个意外跟踪的构建产物。

版本语法变化

Turborepo v2.x 使用 tasks 而不是已弃用的 pipeline 键。从旧规范实施时,务必查看最新文档。

为什么这很重要

大多数 monorepo 迁移都是关于规模的(Google、Meta 管理数千个服务)。我们的迁移是关于清晰度

当您的 CTO 是 Claude,而 CEO 在业务战略和技术实施之间切换时,减少认知负担很重要。一个代码库,一个真相,一个命令运行所有内容。

目标:减少协调基础设施的时间,增加照亮卓越品牌的时间。

接下来是什么

当前:让 monorepo 稳定 2-3 周。我们不追求理论优化。

未来(如果需要):

  • 远程缓存(Turborepo Cloud)
  • CI/CD 优化(受影响任务检测)
  • 共享工具包

目前?我们在构建功能,而不是基础设施。