2023-12-12-【架构】lerna与turbo
在 Monorepo 管理工具的演进史上,Lerna 是曾经的统治者,而 Turborepo 是现代的高性能标杆。随着 Lerna 在 v6 版本后被 Nx 团队接管并重写底层,两者的边界变得模糊,但底层哲学依然有着显著差异。
以下从 构建机制、包管理逻辑、发布工作流 以及 生态集成 四个维度进行深度对比。
1. 构建机制与性能:计算缓存 VS 任务排期
这是 Turborepo 领先的核心领域。
- Turborepo (指纹校验缓存): 它使用 指纹 (Hashing) 技术。它会根据文件内容、依赖项和环境变量生成一个哈希值。如果该哈希值对应的任务结果已存在于缓存中,Turbo 会直接“重播”终端输出并瞬间还原构建产物。
- Lerna (基于 Nx 引擎): 在 v5 之前,Lerna 只是简单的循环执行。从 v6 开始,Lerna 默认集成 Nx,也获得了强大的本地缓存能力。但由于 Lerna 需要兼容大量的历史遗留配置,其在纯构建速度上略逊于由 Rust 编写核心的 Turbo。
2. 任务流管理:拓扑排序 VS 图计算
如何处理 A 依赖 B 时的构建顺序。
- Lerna: 提供显式的依赖拓扑排序。你可以通过命令指定执行顺序,例如先构建所有依赖项,再构建应用。它的管理方式更接近传统的脚本自动化。
- Turborepo (Pipeline 模式): 通过
turbo.json定义任务图谱。
1 | |
Turbo 的并行度更高,它能精确计算出哪些包的 test 不需要等待其他包的 build 完成,从而最大化利用 CPU。
3. 包发布 (Publishing) 工作流:全能管家 VS 纯粹构建
这是两者的核心分水岭。
| 特性 | Lerna | Turborepo |
|---|---|---|
| 版本管理 | 极其强大。支持同步版本(Fixed)和独立版本(Independent)。 | 无。不干预版本逻辑。 |
| Changelog | 内置。自动解析 Git Commit 生成更新日志。 | 无。需第三方工具。 |
| NPM 发布 | **内置 lerna publish**。处理 Tag、OTP、Git 推送。 |
无。需手动编写脚本或结合 Changesets。 |
- Lerna 依然是目前管理 开源多包项目(如 Babel, Jest)的首选,因为它解决了“如何优雅地发布 50 个相互依赖的包”这一难题。
- Turborepo 专注于 业务单体大仓。它假设你不需要频繁向 NPM 发布包,而是频繁地部署 Web 应用或微服务。
4. 包管理底层:Link 逻辑
- Lerna: 早期依赖
lerna bootstrap手动创建node_modules软链接。现在的 Lerna 建议完全交给包管理器(pnpm/yarn/npm)的 Workspaces 功能,自己只负责逻辑调度。 - Turborepo: 从诞生之日起就不负责包管理。它要求你必须使用
pnpm、yarn或npm的 Workspaces。它像一把手术刀,只切入构建那一层,不改变你的包安装结构。
5. 综合选型决策表
| 你的项目需求 | 推荐方案 | 原因 |
|---|---|---|
| 大型开源组件库 | Lerna + pnpm | 必须使用 Lerna 强大的版本发布逻辑。 |
| 企业级全栈 SaaS | Turborepo + pnpm | 极其依赖远程缓存和极速的任务执行,发布流程走 Docker/CI 而非 NPM。 |
| 从旧版 Lerna 升级 | Lerna v8 | 成本最低,且能获得 Nx 的缓存加速。 |
| 追求开发体验与速度 | Turborepo | Rust 底层带来的毫秒级任务分发响应。 |
总结:两者的共生关系
现代 Monorepo 的最佳实践往往不是“二选一”,而是组合拳:
- 使用 pnpm Workspaces 处理物理包的依赖管理和软链接。
- 使用 Turborepo 处理日常的
dev、build、test任务流和缓存。 - 使用 Changesets 或 Lerna 来专门处理发布 NPM 时的版本升级和 Changelog。
既然您在 Nuxt 3 中研究高性能转换,大概率会涉及多包复用。您是想将图片处理逻辑做成一个公共库在多个 Nuxt 实例中共享吗? 如果是,我可以为您提供一份 turbo.json 的具体配置模版。
2023-12-12-【架构】lerna与turbo
https://zhangyingxuan.github.io/2023-12-12-【架构】lerna与turbo/