Monorepo 架构:Lerna、Nx 与 Turborepo 的对比

10 阅读3分钟

随着前端工程的日益复杂,Monorepo 架构已逐渐成为大中型项目的首选方案。在本文中,我们将系统性地对比和解析 Lerna、Nx 与 Turborepo 三种常见 Monorepo 工具,从原理到实践,助你选择合适的技术方案。

什么是 Monorepo?

Monorepo(单体仓库)是一种将多个模块(package)集中在同一个 Git 仓库中管理的策略。这些模块可以是组件库、业务应用、工具函数库等,通过工具辅助实现版本管理、构建调度、依赖分析等功能。

三大主流工具对比:Lerna vs Nx vs Turborepo

功能/工具LernaNxTurborepo
包管理依赖 Yarn/NPM/PNPM内置或支持现有包管理器建议搭配 PNPM 使用
构建缓存❌ 不支持✅ 支持任务级别缓存✅ 支持任务级别缓存
构建调度❌ 无✅ 有依赖图和调度机制✅ 有依赖图和调度机制
可视化工具❌ 无✅ nx graph✅ turbo run graph
支持语言JS/TS多语言支持(如 React、Nest)主要为 JS/TS
学习曲线⭐ 简单⭐⭐⭐ 复杂但强大⭐⭐ 相对友好

Lerna 的定位

Lerna 主要专注于包的版本管理与发布。

  • 强项:管理多个 npm 包、版本发布、变更检测
  • 搭配方式:常与 Yarn Workspaces 搭配使用
  • 缺点:无缓存,无任务调度,构建需手动编排

Nx 的优势与实践

Nx 是一款强大的 Monorepo 工具,适合大型项目,提供:

  • 精细化的 依赖图管理
  • 内建的 任务调度系统
  • 丰富的命令如 nx run, nx affected, nx graph
  • 任务级缓存(基于任务输入/依赖自动生成哈希)

示例命令

npx nx graph --focus=admin-dashboard       # 生成指定模块的依赖图
npx nx affected:graph --base=main --head=HEAD  # 展示变更影响

Turborepo 的亮点

Turborepo 是 Vercel 推出的现代化构建工具,主打:

  • 极速构建(本地 + 远程缓存)
  • 精准调度(只构建有改动的任务)
  • 配置简洁(turbo.json

缓存机制:

project:task 粒度缓存,比如:

  • ui-button:build
  • ui-button:test

会根据源文件、配置、依赖产物等生成哈希进行缓存匹配。

缓存细节:任务级缓存,不是文件级!

ui-button 为例:

  • 改动 src/Button.tsx → 会触发整个 ui-button:build 任务重新执行
  • 但只影响 build 任务,lint/test 可从缓存中读取

缓存粒度为 project + task,非文件级。

Nx + Lerna 能否组合使用?

先说结论:可以

  • Nx 管理任务调度、缓存、依赖分析
  • Lerna 继续管理版本发布、changelog 等

为什么 Turbo 推荐配合 pnpm 使用?

  • pnpm 的 node_modules 结构与 Turbo 的依赖分析更契合
  • pnpm 构建快、占空间小、支持软链接逻辑简单

Yarn Workspace 与 Monorepo 工具的关系

Yarn Workspace 提供基础包管理能力(install、link),但:

  • ❌ 无调度能力
  • ❌ 无缓存能力

Turbo 和 Nx 则是在其之上提供:

  • 构建调度
  • 缓存分析
  • 依赖追踪

如何查看/分析依赖图(以 Nx 为例)

npx nx graph                     # 查看全量依赖图
npx nx graph --focus=ui-button  # 聚焦某个模块依赖链
npx nx affected:graph           # 查看受改动影响模块

可用于构建优化、依赖梳理、调度策略设计。

总结:选型建议

项目类型推荐工具组合
小型组件库 MonorepoYarn Workspaces + Lerna
中大型前端项目Nx 或 Turborepo + pnpm
需要发布多个包Lerna + Turbo/Nx

结语

选择合适的 Monorepo 工具,不只是构建速度的问题,更是未来团队协作、模块扩展、工程治理的基础能力。希望本文的对比与实践能为你的项目提供清晰的方向。