🐭Monorepo🐭三部曲-工具篇
上一篇我们讲述了Monorepo
相关理论,但我们如何把自己项目给搭建成Monorepo
的仓库呢?这种就需要用工具进行搭建,那要用哪些工具呢?他们适用场景和优缺点都是什么呢?这些都会在本篇文章进行讲述,有哪些工具呢?他们适用场景和优缺点都是什么呢?这些都会在本篇文章进行讲述,而在下一篇文章会选择其中一个工具进行Monorepo
项目的搭建过程。
话不多说,直接开干。
前言
在采用单一仓库(Monorepo)架构的软件开发中,选择合适的工具至关重要。优秀的Monorepo工具可以帮助团队更有效地管理大规模代码库,提升协同开发体验,优化构建和部署流程。
截至2024年,目前在前端领域比较流行的Monorepo工具包括Rush
、Turborepo
、Lerna
、Yarn Workspaces
、Pnpm Workspaces
、Yalc
、npm Workspaces
和Nx
。以下将简要介绍下这些热门工具。
这里我们来看一份2022年的调研结果,数据来自:2022.stateofjs.com/zh-Hans/lib…
该图表会根据代码库的满意度对代码库进行排名 满意度指的是“会再次使用这个库的人数”。 请注意,使用率不到 10% 的代码库不包括在内。
这里我们看到比较常用的Monorepo工具,按照使用频率依次是:
Pnpm Workspaces
Nx
npm Workspaces
Yarn Workspaces
Lerna
除了上述五个,本文还会介绍:
Rush
Turborepo
Pnpm Workspaces
pnpm workspace
是pnpm包管理工具的一个功能模块,专注于支持Monorepo(单一仓库)的工作区管理。通过高效的依赖共享机制,pnpm workspace能够集中管理多个相关的包,实现更快速、更节省空间的依赖安装和执行
。
该工具提供了命令行工具,支持多包管理、依赖共享、版本一致性维护、脚本运行等功能,使得在单一仓库中管理多个包变得更为便捷和高效。虽然可能存在学习曲线和部分生态支持的挑战,但在Monorepo场景下,pnpm workspace的优势在于提供了快速、节省空间、版本一致性等方面的综合解决方案。
PNPM Workspaces 提供了一种管理多个包或项目的便捷方式,但它也有一些优点和缺点。
优点:
- 共享依赖:PNPM Workspaces 可以在工作空间中共享依赖项,这意味着相同版本的依赖只会被下载和存储一次,从而节省了磁盘空间和下载时间。
- 统一版本管理:通过使用 PNPM Workspaces,你可以轻松地在所有子包中统一管理依赖的版本,避免版本冲突和维护困难。
- 便于代码重用:工作空间使得不同包之间的代码共享变得更加容易,可以更方便地重用和组合代码。
- 简化项目结构:将多个相关的包放在一个工作空间下有助于简化项目结构,减少冗余文件和目录,并提高代码的可读性和维护性。
- 支持并行操作:PNPM Workspaces 支持并行安装和执行命令,可以提高开发效率。
缺点:
- 依赖关系复杂性:当工作空间中包之间的依赖关系变得复杂时,管理和解决依赖冲突可能会变得困难。
- 工具支持:虽然 PNPM 提供了 Workspaces 功能,但并非所有的工具和插件都对 PNPM Workspaces 提供良好的支持,可能会导致一些兼容性和使用上的问题。
综上所述,PNPM Workspaces 在管理多个包或项目时提供了一些便利和优势,但也需要权衡其带来的学习成本、复杂性和潜在的性能问题。根据具体项目的需求和规模,可以考虑是否使用 PNPM Workspaces 来提高开发效率和管理多包项目。
Nx
Nx
(Nrwl Extensions)是一个开源工具,专为管理和开发大型Monorepo项目而设计。它建立在Angular CLI之上,提供了一套功能强大的工具和插件,支持多语言、多框架的项目。Nx的核心理念是通过插件化的方式,为开发者提供更高层次的抽象,以提高项目的可维护性、可扩展性和开发效率。Nx支持生成可重用的领域库、定义和执行一致的工作流,以及提供强大的可视化工具来监控项目和性能。
Nx 是一个功能强大的 monorepo 工具,它具有许多优点,也存在一些缺点。以下是关于 Nx 的优缺点总结:
优点:
- 多语言支持:Nx 支持多种前端和后端框架,包括 Angular、React、NestJS 等,使其适用于各种技术栈的项目。
- 智能构建系统:Nx 的增量构建和缓存功能可以显著提高构建速度,只需要重建变更部分,从而节省时间和资源。
- 全面的可视化工具: Nx 提供了全面的可视化工具,帮助开发者更好地理解项目结构、监控性能,并提供快速导航和跳转。
- 插件生态系统:Nx 拥有丰富的官方和社区插件,可以扩展其功能,满足不同项目的需求。
- 良好的扩展性:Nx 具有良好的扩展性,可以根据项目需求进行定制和扩展,使其适用于各种复杂的项目场景。
缺点:
- 学习曲线:由于 Nx 功能强大且功能丰富,因此学习成本较高,新用户可能需要花费一定时间来掌握其各项功能和用法。
- 依赖于Angular:Nx的核心建立在Angular CLI之上,因此对于不使用Angular框架的项目可能显得过于重量级。
- 配置复杂性:对于小型项目来说,Nx 的配置可能显得过于复杂,一些功能可能显得过剩或不必要。
综上所述,Nx 作为一个 monorepo 工具,在大型项目和多团队协作中具有明显的优势,但需要注意其学习曲线和配置复杂性。对于需要管理复杂项目的团队来说,Nx 是一个非常强大的工具,可以帮助他们提高开发效率、项目维护性和可扩展性。
Npm Workspaces
Npm Workspaces
是 npm 包管理器提供的一种功能,用于管理 Monorepo中的多个项目。它允许开发人员在一个仓库中同时管理多个相关项目,并共享依赖项。npm Workspaces提供了一系列命令和配置,使得开发者可以更便捷地进行多包的管理,如依赖安装、脚本执行等。尽管在某些方面不如其他专业的Monorepo工具强大,npm Workspaces提供了一种相对轻量级的方案,适用于一些小型或者简单的Monorepo项目,无需引入额外的复杂性。
Npm Workspaces 是 npm 包管理器提供的一种功能,用于管理 Monorepo(多包存储库)中的多个项目。它允许开发人员在一个仓库中同时管理多个相关项目,并共享依赖项。以下是 Npm Workspaces 的一些特点:
优点
- 简单易用: npm Workspaces 提供了一种相对简单的 Monorepo 管理方案,易于上手和使用。
- 依赖管理简单:共享依赖,节省磁盘空间和安装时间。
- 版本一致性:所有包使用同一个
node_modules
和锁文件,确保版本一致。 - 简化 CI/CD:集中管理多个包,构建和发布流程更清晰。
缺点
- 增加复杂性:需要学习和掌握工作空间的管理方式。
- 工具兼容性:部分工具可能不完全支持工作空间,需要额外配置。
- 性能问题:随着项目规模的增大,npm Workspaces的性能可能会受到影响,特别是在进行依赖安装时。
Yarn Workspaces
Yarn Workspaces
是Yarn包管理器的一个强大功能,专注于优化Monorepo项目的依赖关系管理。该功能允许将多个包组织在同一个版本控制存储库中,在解决版本冲突问题时统一依赖版本,并通过共享顶层node_modules目录来有效减小磁盘占用
。
Yarn Workspaces支持交叉包引用,提供了更灵活的项目组织方式,并通过并行安装来加速整体构建速度。这个轻量级而功能强大的Monorepo解决方案,特别适用于中小型项目和对简单性要求较高的团队。
Yarn Workspaces 是 Yarn 提供的一个特性,它允许你在一个存储库中维护多个包(packages)和项目。类似于 Pnpm Workspaces,Yarn Workspaces 也具有以下优缺点:
优点:
- 依赖一致性: 所有包共享相同的依赖版本,确保一致的开发环境。
- 简化依赖管理: 单个根目录管理所有包的依赖关系,减少潜在的版本冲突。
- 便于代码共享: 不同的包可以轻松共享和重用相同的代码库。
- 节省磁盘空间: Workspaces 利用符号链接(symlinks)共享相同版本的依赖包,避免重复安装相同的依赖。
缺点:
- 需要额外配置: 设置 Workspaces 需要一些初始配置工作。
- 与一些工具集成不佳: 虽然大多数工具与 Workspaces 集成良好,但可能偶尔会遇到一些问题。
- 功能相对简化:与一些专注于Monorepo管理的工具相比,Yarn Workspaces的功能相对简化,可能不适用于所有复杂的项目结构。
总的来说,Yarn Workspaces 非常适合于管理中大型的多包应用程序,特别是具有许多共享依赖项的项目。它可以显著提高开发效率、减少磁盘占用并简化依赖管理。
Lerna
Lerna
是一款专为管理具有多个软件包的JavaScript项目而设计的工具,旨在优化大型Monorepo项目的版本管理、依赖共享以及发布流程。通过提供一套强大的命令行工具,Lerna简化了Monorepo项目的操作,使开发者能够更轻松地管理和维护庞大的代码库,提高开发效率和代码的可维护性。
优点
- 版本一致性:统一管理所有包的版本号,确保一致性。
- 依赖共享:各包可共享相同的依赖版本,避免重复安装。
- 发布自动化:Lerna支持自动化的发布过程,能够一次性发布所有更新的软件包,提高了发布的效率。
- 操作简便: 具备强大的命令行工具,使得 Monorepo 项目的操作变得简单易行,包括软件包的添加、删除、测试等。
缺点
- 学习曲线:使用 Lerna 需要一定的学习成本,特别是对于新手来说,可能需要一些时间来熟悉其工作原理和命令。
- 依赖关系处理:有时候 Lerna 的依赖管理可能会出现一些问题,例如依赖冲突或版本不一致的情况。
- 维护成本:在使用 Lerna 进行项目管理时,需要花费一定的时间和精力来维护和管理多个包,增加了一定的维护成本。
Rush
Rush是一个由
微软
开发并用于管理和构建大型的多包仓库。Rush 提供了一系列工具和最佳实践来帮助开发者高效地管理和构建 Monorepo 项目。
关键特性
- 增量构建:Rush 能够检测代码变化,仅重新构建受影响的模块,提高了构建效率。
- 版本控制:支持多种版本策略,包括单版本策略和独立版本策略。
- 集成工具:与常用工具如 TypeScript、Webpack、Babel 等无缝集成。
- 依赖管理:使用 pnpm、Yarn 或 npm 来管理依赖。
- 任务并行化:利用现代多核处理器,通过任务并行化加快构建速度。
- 变更日志和发布:自动生成变更日志,并支持集成发布流程。
缺点
- 学习曲线:对于新用户来说,Rush可能有一定的学习曲线,需要花一些时间来熟悉其工作原理和使用方法。
- 配置复杂性:配置Rush可能需要一些复杂的设置和调整,特别是对于大型Monorepo项目而言。
- 依赖版本冲突:在Monorepo中,可能会出现依赖版本冲突的情况,需要仔细管理和解决这些冲突。
安装和设置 Rush
要开始使用 Rush,你需要先安装它。确保你已经安装了 Node.js,然后可以通过 npm 全局安装 Rush:
npm install -g @microsoft/rush
初始化新项目
-
创建一个新的项目目录:
mkdir my-monorepo cd my-monorepo
-
初始化 Rush:
rush init
这将在你的项目目录中创建一个名为 rush.json
的配置文件,该文件是 Rush 的核心配置文件。
配置你的 Monorepo
你需要在 rush.json
文件中定义你的项目结构和设置一些基本的配置。例如,定义你的项目根目录、使用的包管理器等。这里是一个简单的例子:
{
"$schema": "https://developer.microsoft.com/json-schemas/rush/v5/rush.schema.json",
"rushVersion": "5.47.0",
"pnpmVersion": "6.14.0",
"nodeSupportedVersionRange": ">=14.0.0 <15.0.0",
"projectFolderMinDepth": 1,
"projectFolderMaxDepth": 2,
"projects": [
{
"packageName": "my-app",
"projectFolder": "apps/my-app"
},
{
"packageName": "my-lib",
"projectFolder": "libs/my-lib"
}
]
}
添加项目
在 apps
或 libs
目录中添加你的项目。每个项目应该包含一个 package.json
文件。例如,在 apps/my-app
下创建一个新的 Node.js 项目:
mkdir -p apps/my-app
cd apps/my-app
npm init -y
安装依赖
运行以下命令来安装所有项目的依赖:
rush update
构建项目
使用 Rush 构建你的项目:
rush build
增量构建
Rush 支持增量构建,只构建那些自上次构建以来有变化的部分:
rush build --incremental
发布项目
Rush 提供了发布管理的功能,可以自动生成变更日志并发布新的版本:
rush publish
执行自定义任务
你可以在 command-line.json
文件中定义自定义任务。例如,定义一个清理任务:
{
"$schema": "https://developer.microsoft.com/json-schemas/rush/v5/command-line.schema.json",
"commands": [
{
"commandKind": "bulk",
"name": "clean",
"summary": "Cleans the project.",
"description": "This command runs the 'clean' script in each project's package.json.",
"safeForSimultaneousRushProcesses": true
}
],
"bulkCommands": [
{
"name": "clean",
"commandToRun": "npm run clean"
}
]
}
然后可以运行自定义任务:
rush clean
Turborepo
Turborepo
是由原Webpack团队
推出的一个智能构建系统,专为优化JavaScript和TypeScript代码库而设计
。Turborepo利用缓存来增强本地设置,并加快持续集成(CI)速度
。Turborepo具有开箱即用的特点,可以与npm、pnpm和yarn等单版本工具一起使用
。
Turborepo 是一种用于管理 Monorepo 项目的工具,它提供了一系列特性来优化和加速多包项目的开发过程。以下是 Turborepo 的一些优点和缺点。
优点
- 并行化构建:通过智能地并行化构建任务,Turborepo 能充分利用多核处理器,从而显著提升构建速度。这对于大型项目尤其重要。
- 增量构建:仅重新构建发生变化的部分,避免了不必要的全局重建,从而大幅度提高构建效率。
- 缓存优化:Turborepo 引入了先进的缓存机制,可以存储和重用先前的构建结果,减少重复工作的时间。这对于频繁的构建和 CI/CD 流程非常有帮助。
- 灵活的配置:Turborepo 提供了灵活且强大的配置选项,能满足不同项目和团队的需求。用户可以根据具体情况定制构建流程和工作流程。
- 工具集成:Turborepo 可以与许多常见的构建工具和框架无缝集成,例如 Babel、Webpack 等,使得现有项目更容易迁移到 Turborepo。
- 开发体验:通过提供一致的构建和执行方式,Turborepo 改善了开发者的体验,减少了开发环境和生产环境之间的差异。
缺点
- 学习曲线:对于新手或没有使用过类似工具的开发者来说,理解和配置 Turborepo 可能需要一些时间。尽管文档详尽,但仍需一定的学习成本。
- 生态系统成熟度:相比于一些已经存在较长时间的 Monorepo 工具(如 Lerna 或 Bazel),Turborepo 的生态系统可能还不够成熟,社区支持和第三方插件相对较少。
- 项目复杂性:对于小型项目或简单的 Monorepo 结构,Turborepo 的高级功能可能显得有些过于复杂,增加了不必要的管理负担。
- 依赖管理:虽然 Turborepo 支持依赖管理,但在处理复杂依赖关系时可能仍会遇到一些挑战,尤其是在处理交叉依赖和版本冲突时。
- 性能瓶颈:尽管 Turborepo 优化了很多方面的性能,但在极端情况下(如非常大的代码库或高度复杂的依赖树),仍可能遇到性能瓶颈,需要额外的调优工作。
Turborepo 是一个功能强大且灵活的 Monorepo 管理工具,特别适合大型项目和需要高效构建流程的团队。它的并行化构建、增量构建和缓存优化等特性可以显著提高开发和构建效率。然而,对于小型项目或刚开始接触 Monorepo 的团队,可能需要考虑学习曲线和复杂性带来的影响。在选择是否使用 Turborepo 时,应根据项目规模、团队熟悉程度以及具体需求进行权衡。
参考文献
转载自:https://juejin.cn/post/7383258697471082546