实战进阶:Monorepo 环境下使用 Changesets 自动化管理语义化版本与发布全流程
在现代前端工程化中,Monorepo(单仓多包)架构已成为大型项目的标配。然而,随着包数量的增加,如何优雅地管理数十个子包的语义化版本(SemVer)、生成更具可读性的 Changelog,以及处理复杂的包间依赖更新,成为了开发者不得不面对的挑战。
传统的 Lerna 虽然经典,但在大型项目中往往显得过于笨重,且其维护状态一度陷入停滞。此时,Changesets 以其“去中心化”、“开发者友好”以及“与 CI/CD 高度集成”的特性,成为了当前 pnpm 或 Yarn Workspaces 架构下的首选方案。
一、 为什么选择 Changesets?
- 非侵入性:在开发阶段只需运行一个简单的命令记录变更。
- 依赖联动:如果 A 包依赖 B 包,当 B 版本升级时,Changesets 会自动识别并提示 A 包是否需要跟随升级。
- 高度可定制:支持自定义 Changelog 生成逻辑。
- CI 友好:官方提供的 GitHub Actions 能够实现从合并 PR 到发布 NPM 的全自动化。
二、 核心工作流拆解
1. 初始化配置
在项目根目录下安装依赖并初始化:
pnpm add -W @changesets/cli
npx changeset init
执行后,根目录会生成 .changeset 文件夹,其中包含 config.json。这是 Changesets 的大脑。
关键配置项:
access: 默认为restricted,如果是开源项目需改为public。baseBranch: 主分支名(如main或master)。ignore: 哪些包不需要发布版本。linked: 强制某些包的版本号保持同步(例如核心库及其插件)。
2. 开发阶段:记录变更(The "Add" Step)
每当你完成一个功能或修复一个 Bug 后,不要直接修改 package.json 中的版本号。运行以下命令:
npx changeset
你会进入一个交互式命令行:
- 选择要发布的包:通过空格选择发生变动的子包。
- 选择版本升级类型:
patch(补丁),minor(功能),major(破坏性更新)。 - 填写变更信息:这段文字会最终出现在生成的
CHANGELOG.md中。
完成后,系统会生成一个随机命名的 .md 文件在 .changeset 目录中。请将该文件随代码一起提交到仓库。
3. 预发布阶段:版本合并(The "Version" Step)
当积累了一定数量的变更,准备发布新版本时,执行:
npx changeset version
这个命令会执行以下操作:
- 消耗掉
.changeset下的所有临时.md文件。 - 根据定义的语义化版本规则,自动更新受影响子包的
package.json。 - 为每个包自动生成或更新
CHANGELOG.md。 - 更新 Monorepo 内部互相引用的版本号(如
workspace:*自动更新为具体数值)。
4. 发布阶段:推送 NPM(The "Publish" Step)
npx changeset publish
该命令会检查本地 package.json 与远端仓库的版本差异,仅发布未曾发布的版本。
三、 进阶:集成 GitHub Actions 实现全自动化
Changesets 的强大之处在于配合 GitHub Actions。我们可以设定这样一个流程:
- 开发者提交代码(包含 changeset 记录文件)。
- 代码合并到
main分支后,Action 运行并自动创建一个名为 "Version Packages" 的 Pull Request。 - 这个 PR 已经帮你运行过
changeset version,包含版本号和 Changelog 的更新。 - 一旦管理员合并这个 PR,Action 会自动运行
changeset publish发布到 NPM。
示例 GitHub Action 配置 (.github/workflows/release.yml):
name: Release
on:
push:
branches:
- main
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: pnpm/action-setup@v2
- uses: actions/setup-node@v3
with:
node-version: 18
cache: 'pnpm'
- name: Install dependencies
run: pnpm install
- name: Create Release Pull Request or Publish
uses: changesets/action@v1
with:
publish: pnpm release # 对应 package.json 中的脚本
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
四、 避坑指南与最佳实践
- Pre-release 模式:如果你需要发布测试版(如
alpha或beta),可以使用npx changeset pre enter alpha。此时所有的版本更新都会带上后缀,直到执行exit。 - Changelog 定制:默认的 Changelog 比较简单。如果需要包含 GitHub 用户名、PR 链接等信息,推荐安装
@changesets/changelog-github并在配置中启用。 - 不要手动改版本号:在 Changesets 体系下,严禁手动修改
package.json里的version字段,否则会导致版本对齐逻辑混乱。 - 原子化提交:尽量保证一个变更记录对应一个功能点,避免在一个 changeset 文件里描述太多不相关的东西。
总结
Changesets 将 Monorepo 繁琐的版本管理工作转化为简单的交互式命令和自动化脚本。对于团队协作而言,它最大的价值在于强制规范化了变更信息的收集过程,让每一行代码的变更都“有迹可循”。如果你的 Monorepo 还在为发布版本而苦恼,那么 Changesets 绝对值得一试。