背景
在公司的Monorepo项目管理中,版本管理一直是一个比较难处理的问题,今天我就介绍用changesets来进行版本控制、版本变更和发布。
在现代软件开发中,Monorepo架构已经成为管理复杂项目的流行选择。它允许我们将多个相关项目或模块集中在一个单一的代码库中。对于使用pnpm monorepo的项目来说,使用changeset可以提供更高效、更可靠的版本控制和发布管理。
pnpm 和 monorepo
首先,让我们来了解一下pnpm monorepo。pnpm是一个快速、可扩展的包管理工具,它允许我们在一个根目录下同时管理多个相关项目。这种架构提供了更好的代码共享和依赖管理,以提高开发效率和代码质量。
pnpm文档:www.pnpm.cn/workspaces
changeset
接下来,让我们了解一下changeset。changeset是一个轻量级的版本控制工具,它主要用于管理项目中的版本变更和发布。使用changeset,我们可以定义项目中的变更,并生成适用于每个变更的语义化版本号。这样,我们就可以更好地控制和维护项目的版本历史,确保依赖关系的兼容性和代码库的稳定性。
changesets文档:github.com/changesets/...
准备
在pnpm monorepo的项目中使用changeset,首先我们要有一个monorepo的项目。使用pnpm创建monorepo项目,具体的可以看我写的这篇文章------《简单讲解怎么用pnpm搭建一个monorepo开源react项目(Vite 和 TypeScript)》,也可以按照以下步骤进行操作:
1. 创建文件夹
创建一个空文件夹作为根目录。例如,可以执行以下命令在当前目录下创建一个名为my-monorepo的文件夹:
perl
mkdir my-monorepo
2. 项目初始化
进入根目录,执行以下命令来初始化pnpm monorepo项目:
bash
cd my-monorepo
pnpm init
3. 构建 monorepo
新建pnpm-workspace.yaml文件。执行以下命令:
makefile
# pnpm-workspace.yaml
packages:
- "apps/*"
- "packages/*"
- "!**/test/**"
4. 创建包文件夹
创建一个名为packages的文件夹,该文件夹将用于存放所有子项目。执行以下命令:
arduino
mkdir packages
5. 创建子项目
进入packages文件夹,创建子项目的文件夹。每个子项目都可以是一个独立的模块。例如,可以执行以下命令来创建一个名为my-package的子项目:
perl
cd packages
mkdir my-package-one
6. 子项目初始化
进入子项目的文件夹,执行以下命令来初始化子项目:
kotlin
cd my-package-one
pnpm init
7. 构建多项目
重复步骤5至6,以创建和初始化其他子项目。
现在,你已经成功创建了一个pnpm monorepo项目,并在根目录下创建了子项目文件夹。每个子项目都可以拥有自己的独立依赖项并进行单独的开发。最后完整项目如下图:

需要注意的是,在根目录下运行pnpm的命令时,它会根据每个子项目的依赖关系自动安装和管理依赖项。这使得依赖项的复用更加高效,并确保所有子项目共享同一版本的依赖项。
通过使用pnpm创建monorepo项目,我们可以更好地管理和维护多个相关项目,并提高开发效率和代码质量。每个子项目都可以独立于其他项目进行开发,同时共享相同的依赖项和版本控制。这种集中式的代码管理方式为团队协作提供了更好的灵活性和可扩展性。
使用
在pnpm monorepo的项目中使用changeset,我们可以按照以下步骤进行操作
安装 changesets
要在 pnpm 工作区上设置变更集,请将变更集作为开发依赖项安装在工作区的根目录中
js
# 安装 changesets
pnpm add -Dw @changesets/cli
然后changesets的初始命令:
csharp
# 初始化 changesets 文件夹
npx changeset init
完成后项目会出现一个.changeset的文件夹
lua
|-- my-monorepo
|-- .changeset
|-- config.json
|-- README.md
|-- ...
配置 changestes
配置 .changeset/config.json
默认配置,如下:
json
{
"commit": false,
"updateInternalDependencies": "patch",
"linked": [],
"access": "restricted",
"baseBranch": "master",
"ignore": [],
"changelog": "@changesets/cli/changelog"
}
修改 packages.json
修改项目根目录的 package.json
js
// package.json
// 新增
"scripts": {
// 构建整个项目的产物
"build": "pnpm -r --filter ./packages run build",
// 1. 开始交互式填写变更集
"changeset": "changeset",
// 2. 用来统一提升版本号
"vp": "changeset version",
// 3. 构建产物后发版
"release": "pnpm build && pnpm release:only",
"release:only": "changeset publish --registry=https://registry.npmjs.com/"
}
执行命令
- 开始交互式填写变更集
我是win10的电脑可以,打开windows powershell执行,下面的命令:
js
pnpm changeset
注意:git 不行,因为无法使用键盘选择。
效果如下:

选择完要提交的包,之后写入Summary,如下图:

操作完之后.changeset的文件内就会多一个*.md文件。
- 统一提升版本号 完成上面的操作后,再统一提升版本号,使用下面的命令:
js
pnpm vp
操作完之后子项目的文件内就会多一个CHANGELOG.md文件,并且package.json文件的项目版本也会提升。
js
{
- "version": "1.0.0",
+ "version": "2.0.0",
}
说明
业务项目发布流是怎么样的?
- 不同开发者先开发,在提交
PR时使用pnpm changeset写入一份变更集。 - 定期项目
owner发包,使用pnpm vp消耗所有变更集,由changesets自动提升子包版本、生成changelog。 - 执行
pnpm release构建全部项目并发包。

总结
总之,在pnpm monorepo的项目中使用changeset是一种高效、规范的版本控制和发布管理方法。它可以帮助开发者更好地管理包之间的依赖关系,并提供更可靠的代码库维护和版本历史追踪。通过结合pnpm monorepo和changeset,我们可以更高效地构建和维护复杂的软件项目。