什么是Monorepo?
Monorepo 是一种项目代码管理方式,指单个仓库中管理多个项目,有助于简化代码共享、版本控制、构建和部署等方面的复杂性,并提供更好的可重用性和协作性。
阶段一:单仓库巨石应用, 一个 Git 仓库维护着项目代码,随着迭代业务复杂度的提升,项目代码会变得越来越多,越来越复杂,大量代码构建效率也会降低,最终导致了单体巨石应用,这种代码管理方式称之为 Monolith。
阶段二:多仓库多模块应用,于是将项目拆解成多个业务模块,并在多个 Git 仓库管理,模块解耦,降低了巨石应用的复杂度,每个模块都可以独立编码、测试、发版,代码管理变得简化,构建效率也得以提升,这种代码管理方式称之为 MultiRepo。
阶段三:单仓库多模块应用,随着业务复杂度的提升,模块仓库越来越多,MultiRepo这种方式虽然从业务上解耦了,但增加了项目工程管理的难度,随着模块仓库达到一定数量级,会有几个问题:跨仓库代码难共享;分散在单仓库的模块依赖管理复杂(底层模块升级后,其他上层依赖需要及时更新,否则有问题);增加了构建耗时。于是将多个项目集成到一个仓库下,共享工程配置,同时又快捷地共享模块代码,成为趋势,这种代码管理方式称之为 MonoRepo。
优势
- 便于管理多个相互依赖的项目;
- 便于团队共享知识库;
- 减少项目管理的成本;
劣势
- 版本管理混乱;
- 代码质量参差不齐,相互影响;
- 技术栈升级困难;
- 难以进行权限管理;
适用场景
充分条件
- 多个项目之间相互依赖;
- 功能,版本之间存在强关联;
- 项目中存在多个编译入口,且构建条件存在差异;
次要条件
- 希望在团队中共享知识库(代码库);
- 降低项目管理成本;
pnpm
pnpm 全称是 “Performant NPM”,即高性能的 npm。它结合软硬链接与新的依赖组织方式,大大提升了包管理的效率,也同时解决了 “幽灵依赖” 的问题,让包管理更加规范,减少潜在风险发生的可能性。
安装命令: npm i pnpm -g
pnpm的优势
- 快速,pnpm会将包缓存到本地,减少二次安装需要的时间;
- 节省磁盘空间:它会把包硬链接到项目本地,不需要反复安装;
- 更好的依赖处理逻辑(pnpm可以解决Monorepo项目中存在的幽灵依赖和包的重复引用问题);
幽灵依赖是指,项目代码引用的某个包没有直接定义在 package.json
中,而是作为子依赖被某个包顺带安装了。
Monorepo 实战
一,创建Monorepo工程
创建一个文件夹并cd到该文件夹下执行 pnpm init
,获得一个 package.json
文件.
创建一个pnpm-workspace.yaml文件(此文件定义了该工程工作空间的目录结构),并将如下的内容粘贴至文件内:
packages:
# 所有子包的位置
- 'packages/*'
# 所有子包/项目公用的组件
- 'components/**'
# 所有的api
- 'api/**'
# 公用的工具函数
- 'utils/**'
二,创建子项目
创建packages文件夹并在其路径下执行npm create vue@latest
创建两个子项目,之后使用pnpm install
安装依赖.
三,创建并使用项目依赖的公共部分
项目公共部分的使用基本可以分为三种情况:
- 没有其他依赖的工具类函数或者静态资源;
- 有依赖库的工具类;
- 公共的UI组件;
1,没有其他依赖的工具类函数或者静态资源
- 创建utils文件夹,
pnpm init
并修改package.json文件; - 定义并导出公共函数;
- 在子项目中使用
pnpm add xxx
引入工具包;
2.有依赖库的工具类
这里以封装请求工具为例:
- 创建api文件夹,
pnpm init
并修改package.json文件; - 安装axios并对其进行简单封装;
- 在子项目中使用
pnpm add xxx
引入工具包;
3.公共的UI组件
- 使用
npm create vite
创建一个vue项目,需要包含vue相关才能定义vue组件; - 工程创建成功之后删除其他没有用的文件,留下node_moudles和package.json即可;
- 在子项目中使用
pnpm add xxx
引入工具包;
四,pnpm的一些命令
- 安装
pnpm add xxx
或者pnpm install xxx
; - 卸载
pnpm remove xxx
或者pnpm uninstall xxx
; - 想把插件安装到全局需要使用 -w,例如:安装lodash到全局以保证每个子项目都能直接使用,cd 到顶层文件夹然后执行
pnpm add lodash -w
;