Changeset 版本管理原理
Changeset 是一个用于管理 monorepo 中多个包版本的工具,帮助团队跟踪变更、自动版本管理和生成 CHANGELOG。
什么是 Changeset?
Changeset 是一个用于管理 monorepo 中多个包版本的工具,由 Atlassian 开发。它帮助团队:
- ✅ 跟踪变更:记录每个包的变化
- ✅ 自动版本管理:根据变更类型自动更新版本号
- ✅ 生成 CHANGELOG:自动生成变更日志
- ✅ 发布管理:统一管理包的发布流程
为什么需要 Changeset?
传统版本管理的问题
在 monorepo 中,有多个包(如 @enterprise-ui/core、@enterprise-ui/react19),传统方式的问题:
// ❌ 问题 1:手动管理版本号,容易出错
// packages/core/package.json
"version": "1.0.0" // 需要手动更新
// packages/components-react19/package.json
"version": "1.0.0" // 需要手动更新
// ❌ 问题 2:不知道哪些包需要发布
// 修改了 core,但忘记更新版本号
// ❌ 问题 3:CHANGELOG 需要手动维护
// 容易遗漏或格式不一致
// ❌ 问题 4:依赖关系复杂
// core 更新了,react19 依赖它,需要同时更新Changeset 的解决方案
// ✅ 1. 记录变更意图
pnpm changeset
// 选择包、变更类型、描述
// ✅ 2. 自动计算版本号
pnpm version
// 根据 changeset 自动更新版本
// ✅ 3. 自动生成 CHANGELOG
// 基于 changeset 文件自动生成
// ✅ 4. 统一发布
pnpm release
// 构建、版本更新、发布一步完成Changeset 工作原理
1. 变更记录阶段
当你修改了代码,需要发布新版本时:
# 运行命令
pnpm changeset
# 交互式提示:
🦋 Which packages would you like to include?
❯ ◯ @enterprise-ui/core
◯ @enterprise-ui/react19
◯ docs (ignored)
🦋 What kind of change is this for @enterprise-ui/react19?
❯ patch (修复 bug,向后兼容)
minor (新功能,向后兼容)
major (破坏性变更)
🦋 Please enter a summary for this change:
> 修复 Button 组件在 SSR 环境下的样式问题生成的文件:
会在 .changeset/ 目录下生成一个 markdown 文件(随机文件名):
.changeset/xxxxx.md
---
"@enterprise-ui/react19": patch
---
修复 Button 组件在 SSR 环境下的样式问题2. 版本更新阶段
准备发布时,运行:
pnpm versionChangeset 会执行以下操作:
- 读取所有 changeset 文件:扫描
.changeset/目录 - 计算新版本号:
patch:1.0.0→1.0.1minor:1.0.0→1.1.0major:1.0.0→2.0.0
- 更新 package.json:自动更新版本号
- 更新依赖版本:如果
react19依赖core,会自动更新依赖版本 - 生成 CHANGELOG.md:基于 changeset 文件生成变更日志
- 删除已使用的 changeset 文件:清理已处理的 changeset
3. 发布阶段
pnpm release执行流程:
- 构建所有包:
pnpm build - 发布到 npm:
changeset publish - 创建 git tag:自动创建版本标签
- 推送到远程仓库:
git push --tags
核心原理详解
1. Changeset 文件格式
Changeset 文件使用 YAML 前置元数据 + Markdown 内容:
---
"@enterprise-ui/react19": patch
"@enterprise-ui/core": minor
---
react19: 修复 Button 组件点击事件
core: 新增 debounce 工具函数格式说明:
---:YAML 前置元数据分隔符"包名": 变更类型:指定包和变更类型(patch/minor/major)- 空行后的内容:变更描述(会出现在 CHANGELOG 中)
2. 版本号计算算法
Changeset 遵循 语义化版本(Semantic Versioning):
MAJOR.MINOR.PATCH
1.0.0
│ │ │
│ │ └─ patch: 修复 bug,向后兼容
│ └─── minor: 新功能,向后兼容
└───── major: 破坏性变更版本更新规则:
- 如果当前版本是
1.0.0,选择patch→1.0.1 - 如果当前版本是
1.0.0,选择minor→1.1.0 - 如果当前版本是
1.0.0,选择major→2.0.0
3. 依赖关系处理
Changeset 会自动处理包之间的依赖关系:
// 场景:core 更新到 1.1.0,react19 依赖 core
// packages/components-react19/package.json
{
"dependencies": {
"@enterprise-ui/core": "^1.0.0" // 旧版本
}
}
// 运行 pnpm version 后
{
"dependencies": {
"@enterprise-ui/core": "^1.1.0" // 自动更新
}
}更新策略:
在 .changeset/config.json 中配置:
{
"updateInternalDependencies": "patch"
// 选项:
// - "patch": 只更新 patch 版本
// - "minor": 更新 minor 和 patch 版本
// - "major": 更新所有版本
}4. CHANGELOG 生成机制
Changeset 会根据 changeset 文件自动生成 CHANGELOG:
# @enterprise-ui/react19
## 1.0.1
### Patch Changes
- 修复 Button 组件在 SSR 环境下的样式问题 ([#123](https://github.com/...))
## 1.0.0
### Major Changes
- 初始版本发布CHANGELOG 格式:
- Major Changes:破坏性变更
- Minor Changes:新功能
- Patch Changes:Bug 修复
配置说明
.changeset/config.json
{
"$schema": "https://unpkg.com/@changesets/config@2.3.1/schema.json",
"changelog": "@changesets/cli/changelog", // CHANGELOG 生成器
"commit": false, // 不自动提交
"fixed": [], // 固定版本(一起发布)
"linked": [], // 链接版本(版本号同步)
"access": "restricted", // npm 发布权限
"baseBranch": "main", // 基础分支
"updateInternalDependencies": "patch", // 内部依赖更新策略
"ignore": ["docs"] // 忽略的包(不发布)
}配置项详解
| 配置项 | 说明 | 示例 |
|---|---|---|
changelog | CHANGELOG 生成方式 | "@changesets/cli/changelog" |
commit | 是否自动提交 | false(手动提交) |
fixed | 固定版本组 | [["@enterprise-ui/core", "@enterprise-ui/react19"]] |
linked | 链接版本组 | [["@enterprise-ui/core", "@enterprise-ui/react19"]] |
access | npm 发布权限 | "restricted"(私有)或 "public" |
baseBranch | 基础分支 | "main" |
updateInternalDependencies | 内部依赖更新策略 | "patch"(补丁版本) |
ignore | 忽略的包 | ["docs"](文档不发布) |
实际使用示例
场景 1:修复 Bug
# 1. 修复了 Button 组件的 bug
# 修改了 packages/components-react19/src/components/Button/Button.tsx
# 2. 创建 changeset
pnpm changeset
# 选择:
# - 包:@enterprise-ui/react19
# - 类型:patch
# - 描述:修复 Button 组件点击事件不触发的问题
# 3. 提交代码
git add .
git commit -m "fix: Button 组件点击事件修复"
git push
# 4. 准备发布(在 CI/CD 或本地)
pnpm version
# 版本:1.0.0 → 1.0.1
# 5. 发布
pnpm release
# 发布到 npm场景 2:添加新功能
# 1. 添加了新的 VirtualList 组件
# 新增了 packages/components-react19/src/components/VirtualList/
# 2. 创建 changeset
pnpm changeset
# 选择:
# - 包:@enterprise-ui/react19
# - 类型:minor(新功能)
# - 描述:新增 VirtualList 组件,支持虚拟滚动
# 3. 提交代码
git add .
git commit -m "feat: 新增 VirtualList 组件"
git push
# 4. 准备发布
pnpm version
# 版本:1.0.0 → 1.1.0
# 5. 发布
pnpm release场景 3:破坏性变更
# 1. 重构了 API,不兼容旧版本
# 修改了 Button 组件的 props
# 2. 创建 changeset
pnpm changeset
# 选择:
# - 包:@enterprise-ui/react19
# - 类型:major(破坏性变更)
# - 描述:重构 Button 组件 API,移除 deprecated props
# 3. 提交代码
git add .
git commit -m "BREAKING: 重构 Button 组件 API"
git push
# 4. 准备发布
pnpm version
# 版本:1.0.0 → 2.0.0
# 5. 发布
pnpm release最佳实践
1. 每次 PR 都创建 changeset
# 修改代码后
git checkout -b fix/button-click
# 修改代码...
# 创建 changeset
pnpm changeset
# 提交 changeset 文件
git add .changeset/
git commit -m "fix: Button 组件点击事件修复"2. 合并 PR 前检查 changeset
在 CI/CD 中检查:
# .github/workflows/ci.yml
- name: Check for changeset
run: |
if [ -z "$(git diff --name-only origin/main | grep '.changeset')" ]; then
echo "❌ 没有 changeset 文件"
exit 1
fi3. 发布前检查
# 1. 确保所有 changeset 都已合并
git pull
# 2. 运行版本更新
pnpm version
# 3. 检查生成的 CHANGELOG
cat packages/components-react19/CHANGELOG.md
# 4. 确认版本号正确
cat packages/components-react19/package.json | grep version
# 5. 发布
pnpm release常见问题
Q1: 忘记创建 changeset 怎么办?
可以补创建 changeset:
# 方案 1:补创建 changeset
pnpm changeset
# 方案 2:手动创建文件
# .changeset/xxxxx.md
---
"@enterprise-ui/react19": patch
---
修复说明Q2: 如何撤销 changeset?
# 删除 changeset 文件
rm .changeset/xxxxx.md
# 或者修改内容
# 编辑 .changeset/xxxxx.mdQ3: 如何跳过某个包的版本更新?
// .changeset/config.json
{
"ignore": ["docs", "example"]
}总结
Changeset 的核心价值:
- ✅ 简化版本管理:自动计算版本号,减少人为错误
- ✅ 跟踪变更:记录每个包的变化,便于追溯
- ✅ 自动生成 CHANGELOG:节省时间,格式统一
- ✅ 依赖管理:自动更新内部依赖版本
- ✅ 发布流程:统一管理发布流程
核心思想:
Changeset 通过记录变更意图(changeset 文件),在发布时自动计算版本号、更新依赖、生成 CHANGELOG,实现了版本管理的自动化和规范化。