使用changeset管理monorepo项目
# 前言
monorepo
(将多个项目放在同一个仓库管理)是当前大热的一个多包管理
方案,但是想要用好monorepo
,就需要解决依赖关系的处理以及包的构建
和发布
问题。下文就来介绍一下如何优雅的解决这些问题
# pnpm
强烈安利在monorepo方案中使用pnpm
作为包管理器,pnpm
有着天然的对monorepo的支持
- 内置
workspace
,有着良好的依赖关系管理
,让你无需处处npm link - 独特的依赖管理机制(将所有依赖的依赖都
打平
放置在.pnpm
文件夹内),解决了让人诟病的幽灵依赖问题 - 特有的
filter
机制,让你在轻松筛选
你想处理的子包
# changeset
下面介绍一下主角,changeset
是一个版本管理,发布,以及changelog
文件管理的工具,它可以筛选出你想发布的子包然后为这些包进行版本升级,生成changelog,以及发布新版本。
他的工作流程也很简单
- 首先
筛选
出想更新的包 - 然后
选择
更新版本号 - 接着
写入
更新摘要,此时会生成
一个临时
changelog文件 - 执行
更新
命令,会消耗
这个临时文件生成最终
的changelog,并且更新版本
- 然后执行
发布
命令,就完成了一个包的更新发布
由于Monorepo
方案的特殊性,我们没办法直接通过commit
来生成changelog
,所以此时changeset
这种更新方式就显得尤其有用,虽然他看上去会比较繁琐。
下面通过一个例子来真实感受一下
首先通过pnpm创建一个monorepo工程并创建几个子包
pnpm-changsets-monorepo-example
├── LICENSE
├── package.json
├── packages
| ├── a
| | ├── CHANGELOG.md
| | ├── index.ts
| | └── package.json
| ├── b
| | ├── CHANGELOG.md
| | ├── index.ts
| | └── package.json
| └── c
| ├── CHANGELOG.md
| ├── index.ts
| └── package.json
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
几个子包的依赖关系如下: c包独立,a包是b包的依赖
这里再提一点pnpm
的强大之处,例如此时我们a包和b包有更新,需要发版。此时因为a包和b包之间存在依赖关系
,正常来说我们需要等待a包构建发布
完毕再去发布b包
。
而pnpm其实早已帮我们处理好了这一切,当我们同时构建这两个包的时候,pnpm内部会自行检测依赖关系
,并且先执行被依赖的包
的构建最后再执行主包的构建
。
回归正题,此时我们有三个包,如果想要更新c包,并且为他生成他自己的changelog。
首先安装一下changeset
pnpm i @changesets/cli
然后执行初始化命令
changeset init
执行后你就会看到在根目录生成了.changeset文件夹,里面有changeset的配置
{
"$schema": "https://unpkg.com/@changesets/config@2.3.1/schema.json",
"changelog": "@changesets/cli/changelog",
"commit": false,
"fixed": [],
"linked": [],
"access": "public",
"baseBranch": "master", //这里修改成你的主分支名
"updateInternalDependencies": "patch",
"ignore": []
}
2
3
4
5
6
7
8
9
10
11
12
开始更新,先执行
changeset 或者 npx changeset
执行次命令后控制台就会罗列
出package下的所有子包
,按空格
选择你想要更新的包,然后按回车
确定
这时候控制台会展示需要更新
的版本号
,是大版本
还是小补丁
,一共三个
选择,对应了语义化版本号管理的三个值。
但是这里不是罗列出来让你选了,而是你要一个一个去确认,不是你想跟新的位数直接输入n
跳过就行了。
当版本号确定后就会出现让你输入摘要
,这个摘要就是最后写入changelog
的内容
输入完摘要就会生成一个临时
的md文件。
这个时候执行以下命令消耗
掉这个临时文件
changeset version
这样就可以看到版本号更新了,以及changelog也生成了。
发布版本
changeset publish
以上就是一个完整的使用过程了