在软件开发的浩瀚宇宙里,选择合适的代码管理方式是构建高效开发环境的关键一步。今天,我们将深入探讨两大策略——Monorepo(单体仓库)与MultiRepo(多仓库),并通过使用现代化的包管理工具 pnpm,手把手搭建一个功能完善的 Monorepo 仓库。✨
上图为Multirepo
和Monorepo
对比图,从图中我们可以简要归纳:
Multirepo
是由多个仓库组成的项目管理方式,每个仓库有着独立的工作流、组件与配置Monorepo
则将不同仓库整合成为一个仓库,并共享工作流、组件与配置。Monorepo
——如同一棵枝繁叶茂的智慧之树,每个分支(项目或模块)紧紧依附于主干,共享着同一片沃土(基础配置)与养分供给(依赖库)👑
MultiRepo
——设想一系列精致的花坛,每一处都是独立的世界,拥有自己的气候(配置)与植被(代码)。🌸
选择Monorepo还是MultiRepo,犹如在协作效率与独立灵活性之间寻找平衡点。🎯
总结来说,
monorepo
倾向于**增强协作和代码一致性,而multirepo
则更强调项目独立性和简单性**。选择哪种模式取决于具体团队规模、项目间关联程度、基础设施支持等因素。在github上我们可以看见无论是
element plus
、Ant design
以及vue
,以及其他社区开源的项目都是使用的monorepo
方案来管理他们的项目
一个健康的Monorepo,其目录结构应清晰有序,如下所示:
root
├── .husky # Git钩子,自动化代码检查
├── node_modules # 依赖存放
├── packages # 各项目或包的集合
│ ├── proj1 # 项目1
│ ├── proj2 # 项目2
│ └── ...
├── docs # 文档
├── ... # 其他包
├── .cz-config.js # 提交信息格式化
├── .gitignore # Git忽略规则
├── .prettierrc.js # Prettier格式化配置
├── pnpm-workspace.yaml # pnpm工作区配置
└── README.md # 项目总览
选用pnpm
作为Monorepo
项目中的包管理器主要有以下几个理由:
🎯 硬链接与缓存机制:
pnpm
使用硬链接和符号链接(软链接)来避免在磁盘上重复存储同一依赖的不同副本,显著减少存储空间占用。🎯 更快的速度与更低的磁盘占用:
🎯 原生支持Workspace:
pnpm natively
支持Workspaces
(类似于yarn workspaces
),只需简单的配置就可以轻松管理多个包或项目,这些项目可以在一个仓库中共享依赖。🎯 扁平化依赖结构:
pnpm
保证了依赖树的扁平化,但同时也保持了依赖包之间的隔离,降低了版本冲突的可能性。🎯 简洁的CLI工具:
pnpm
提供的 CLI 工具对于Monorepo
的日常管理任务(如安装、更新、清理依赖)十分友好,可以直接在多个项目中执行命令。🎯 生态系统兼容性:
pnpm
与npm
生态系统的兼容性很高,能够无缝对接大部分支持npm/yarn
的工具和流程。因此,在构建和维护Monorepo时,pnpm凭借其高效的空间利用、快速的依赖管理以及对多项目工作区的良好支持,成为了一个理想的选择。尤其在需要频繁交互和更新多个项目共享依赖的场景下,pnpm的优势尤为突出。
安装/添加依赖:
# 在所有工作区内安装全局依赖
pnpm add <dependency> -w
# 在单个工作区内安装依赖
pnpm add <dependency> -w <workspace-name>
# 安装本地工作区间的依赖
pnpm add <workspace-package>@workspace:<workspace-name>
更新依赖:
# 更新所有工作区的依赖
pnpm update -w
# 更新单个工作区的依赖
pnpm update -w <workspace-name>
清理无用依赖:
# 移除未在package.json中声明的依赖
pnpm prune -w
# 清理缓存
pnpm cache clean
列出工作区依赖:
# 显示所有工作区及其依赖关系
pnpm list -a
# 显示单个工作区的依赖树
pnpm list -w <workspace-name>
…
初始化
pnpm init
修改package.json
的信息
{
"name": "仓库名称",
"version": "1.0.0",
"description": "",
"...": "..."
}
新建pnpm-workspace.yaml
文件
touch pnpm-workspace.yaml
声明对应的工作区
# pnpm-workspace.yaml
packages:
# 主包 存放所有项目的目录
- 'packages/**'
# 存放组件的目录
- 'components/*'
# 组件库使用的示例代码
- 'examples/*'
# 存放文档
- 'docs/**'
# 存放公共库(配置文件、工具函数、模版等)
- 'shared/**'
在根目录创建相应的工作区目录以及示例项目
# 新建`packages`目录
mkdir packages
# 新建`project`工作区
mkdir project
# 新建`components`工作区
mkdir components
# 新建`examples`工作区
pnpm create vite examples
# ...
将所有项目用到的共同依赖的dependencies
和devDependencies
添加到根目录的package.json
中,并在根目录下载依赖到仓库全局锁定,后面创建的项目将沿用这套依赖
pnpm install -w
到此,monorepo已经准备就绪,接下来就可以进行仓库的eslint
、prettier
、commitlint
、husky
等代码规范以及提交规范的配置了。
Monorepo策略通过pnpm的高效管理,实现了代码库的集中与共享,极大提升了大型项目或团队的协同效率。从目录结构规划到依赖管理,每一步都旨在构建一个既强大又灵活的开发环境。无论你是初创项目还是成熟团队,掌握Monorepo的构建与管理,都将是你软件开发之旅的强大助力。🚀