什么是monorepo
monorepo
意为『单一代码库』,对应的则为『多代码库』(multirepos
)。
monorepo
单一代码库是在一个代码库(repo)里包含了多个模块/包(package)。这些模块/包虽然有可能是相关的,但通常在逻辑上是相互独立的。比如vue代码库,packages
目录下包含了很多核心模块,彼此相关,又彼此独立。
├── packages
| ├── pkg1
| | ├── package.json
| ├── pkg2
| | ├── package.json
├── package.json
vs 多代码库
多代码库(`multirepos)指的是每个项目都单独存在一个完全独立的代码库中。
大多数的项目都是多代码库的,相对独立,每个项目可以自由选择使用的技术栈,项目体积也相对较小。
优点
- 一个代码库内维护多个模块/包,便于查找
- 方便版本管理和依赖管理,模块之间的引用和调试也更加方便
- 统一代码库中的编码风格
- 统一的代码构建流程
- 统一生成 changeLog
缺点
- 代码库体积变大,导致一些操作、启动项目等变慢
- 主线破坏会影响到每一个单独模块开发的人
- 代码提交影响人员范围更大
结论
组件库开发更适合monorepo
单一代码库的方式,项目开发更适合multirepos
多代码库的方式。
pnpm实现monorepo
关于pnpm
的介绍和用法,这里不赘述了,可以看之前的文章:2022年了,你还没用pnpm吗?
初始化
初始化生成package.json
文件
pnpm init
pnpm-workspace.yaml
新建pnpm-workspace.yaml
文件,定义工作空间的根目录,并能够使您从工作空间中包含 / 排除目录 。 默认情况下,包含所有子目录。
packages: # 所有在 packages/ 子目录下的 package
- 'packages/**'
# 不包括在 test 文件夹下的 package
- '!**/test/**'
我们就可以在packages
目录下创建多个模块,这里我创建了charts
、components
、utils
3个包
安装全局依赖
安装packages
目录下模块共用的依赖包
示例:安装lodash
安装全局pnpm
npm i pnpm -g
安装lodash
pnpm install lodash
执行上面安装命令,会报错如下:
如果想把它安装到根目录下,执行命令时需要增加-w
标识(或者 --workspace-root
)
pnpm install lodash -w
可以看出,得益于pnpm
的包管理机制,node_modules
目录下只展示了lodash
一个依赖包,lodash
的相关依赖包完全没展示在其中,全都展示在了.pnpm
里面,再通过软链接的形式指向真实的地址,简洁分明,避免了互相依赖的情况。
安装局部依赖
安装packages
目录下每个包的依赖
示例:packages/charts
目录安装echarts
# 进入目录
cd packages/charts
# 安装依赖
pnpm install echarts
安装项目间依赖
packages
目录下的模块之间相互引用,怎么安装呢?
比如charts
模块依赖utils
模块,为了让依赖实时更新最新版本,使用用通配符更新版本。
pnpm add utils@* --filter charts
执行完上述命令,就会在charts
模块安装utils
的依赖,如下图,我们可以在package.json
中的dependencies
看到"utils": "workspace:*"
,这里的workspace:*
匹配的就是本地包,node_modules
目录下也生成了utils
的软连接,utils
包一更新,charts
里引用utils
的地方就会实时更新。
workspace是局部依赖,pnpm publish
会转成真实路径依赖。
monorepo发包changeset
经过上面的步骤,我们已经完成了monorepo
搭建,接下来我们看一下怎么去发布packages
目录下的包。
Changesets
是一个用于 monorepo
项目下版本以及 changelog
文件管理的工具。管理monorepo
项目下子项目版本的更新、changelog
文件生成、包的发布。
github
地址 changesets,在 github 上有大约 快 5k 的 star。
安装
根目录下执行下述命令安装@changesets/cli
pnpm install @changesets/cli -w --save-dev
初始化
执行命令 pnpm changeset init
进行初始化,在项目根目录下生成一个 .changeset
目录,里面会生成一个 changeset
的 config.json
文件。
pnpm changeset init
根据自己配置,修改config.json
文件中的配置:
- changelog: changelog 生成方式
- commit: 不要让 changeset 在 publish 的时候帮我们做 git add
- linked: 配置哪些包要共享版本
- access: 公私有安全设定,内网建议 restricted ,开源使用 public
- baseBranch: 项目主分支
- updateInternalDependencies: 确保某包依赖的包发生 upgrade,该包也要发生 version upgrade 的衡量单位(量级)
- ignore: 不需要变动 version 的包
生成变更集
执行命令pnpm changeset
或 pnpm changeset add
,该命令将询问一系列问题,首先是您要发布的包,然后是每个包的semver bump类型,然后是整个变更集的摘要。在最后一步,它将显示它将生成的变更集,并确认您要添加它。
pnpm changeset
# 或者
pnpm changeset add
最后生成的文件:
发布
执行命令pnpm changeset publish
进行包的发布
pnpm changeset publish
总结
组件库开发涉及到多包时,还是建议使用monorepo
的方式,更方便依赖的管理。