
Changesets 自动化发版Monorepo 版本管理与 Changelog在现代前端 Monorepo单仓多包架构中当仓库中包含数十个互相依赖的子包如my-team/ui、my-team/utils、my-team/icons时团队面临的最头痛的管理难题莫过于——“多包版本升级与发版Publishing Versioning”。在没有规范化发版工具时开发者经常陷入混乱的“人肉发版泥潭”开发者 A 修改了packages/utils中的一个小方法不得不手动修改它的package.json中的version: 1.0.1紧接着发现packages/ui也依赖了utils于是又手动修改了ui的package.json到了真正运行pnpm publish时经常由于遗漏打 Git Tag、忘记更新CHANGELOG.md、或者私自越级发了破坏性大版本Major Version导致整个团队的依赖版本彻底失控传统的lerna或semantic-release存在配置极其繁重、无法精准支持 PR 粒度变更意图记录的硬伤。在现代前端工程化中Changesets 已经成为 Monorepo 版本管理与自动化发版的绝对事实标准被 Vite、Svelte、pnpm、Shadcn UI 等世界级开源项目全量采用。本文将手把手带大家在 Monorepo 中落地基于 Changesets 的声明式变更记录、全自动版本升级、自动生成精准 Changelog 以及 GitHub Actions / GitLab CI 持续发版流水线。Changesets 的核心运转流转拓扑Changesets 的核心哲学是“变更意图在开发者提交 PR 时即时声明Decentralized Intent版本升级与统一发版在合入主干后集中执行Centralized Automation。”┌─────────────────────────────────────────────────────────────┐ │ 1. 开发者日常开发分支 (Feature Branch / PR) │ │ ├── 开发者修改了代码在终端运行: pnpm changeset │ │ ├── 交互式选择: 哪些子包变动了是 patch / minor 还是 major│ │ ├── 输入一行变更说明 (如: fix: 修复 Button 组件禁用状态样式) │ │ └── 本地自动生成一个微型 Markdown 文件: .changeset/lazy-cat-fly.md │ │ └── 随着当前 PR 代码一同提交至 Git │ └──────────────────────────────┬──────────────────────────────┘ │ (PR 经过审查合并入 main 分支) ▼ ┌─────────────────────────────────────────────────────────────┐ │ 2. CI 自动化版本编排阶段 (CI Versioning Bot) │ │ ├── CI 扫描所有合并进来的 .changeset/*.md 意图文件 │ │ ├── 运行 pnpm changeset version 自动计算各子包新版本号 │ │ ├── 自动递归更新依赖当前包的下游兄弟包的 package.json 版本号│ │ ├── 自动生成/追加各子包的 CHANGELOG.md 详细变更日志 │ │ └── 自动在 GitLab / GitHub 发起一个版本合并 PR: Version Packages │ └──────────────────────────────┬──────────────────────────────┘ │ (管理员点击合并该版本 PR) ▼ ┌─────────────────────────────────────────────────────────────┐ │ 3. CI 物理发布阶段 (CI Publish Pipeline) │ │ ├── 运行 pnpm changeset publish 自动发布至 npm 制品库 │ │ └── 自动创建带有签名的高保真 Git Tags (如 my-team/ui1.2.0)│ └─────────────────────────────────────────────────────────────┘生产级初始化与配置实战步骤 1在 Monorepo 根目录安装依赖并初始化pnpm add -D -w changesets/cli pnpm changeset init执行后会在根目录生成.changeset/config.json核心配置文件// .changeset/config.json { $schema: https://unpkg.com/changesets/config/schema.json, changelog: changesets/cli/changelog, commit: false, // 声明哪些包属于关联升级组 (例如所有核心库保持版本严格对齐) fixed: [ [my-team/core, my-team/ui, my-team/utils] ], // 声明内部私有业务包 (不发布到 npm) privatePackages: { version: true, // 允许升级版本号 tag: false }, access: public, baseBranch: main, updateInternalDependencies: patch, ignore: [apps/*] // 忽略业务子应用仅对公共 packages 发版 }开发者日常协作使用 SOP当开发者在本地修复了一个 Bug 或新增了一个特性并准备提交 PR 时1. 运行声明命令pnpm changeset2. 终端交互式选择演示 Which packages would you like to include? ◯ my-team/utils ◉ my-team/ui ◯ my-team/icons Which packages should have a major bump? (Press Enter to skip) Which packages should have a minor bump? (Press Enter to skip) Which packages should have a patch bump? ◉ my-team/ui Please enter a summary for this change: fix(Button): 修复在 disabled 状态下依然触发 onClick 冒泡的 Bug此时本地在.changeset/目录下生成了一个轻量文件.changeset/smart-fox-dance.md--- my-team/ui: patch --- fix(Button): 修复在 disabled 状态下依然触发 onClick 冒泡的 Bug开发者只需将其随同业务代码正常git add . git commit并推送即可CI/CD 自动化持续发版流水线配置在 GitHub Actions 或 GitLab CI 中配置一个全自动的发版工作流# .github/workflows/release.yml name: Monorepo Auto Release on: push: branches: [main] concurrency: ${{ github.workflow }}-${{ github.ref }} jobs: release: name: Release or Version PR runs-on: ubuntu-latest steps: - uses: actions/checkoutv4 with: fetch-depth: 0 # 必须拉取完整 Git 历史以生成 Changelog - uses: pnpm/action-setupv3 with: version: 9 - uses: actions/setup-nodev4 with: node-version: 20 cache: pnpm registry-url: https://registry.npmjs.org/ - run: pnpm install --frozen-lockfile - run: pnpm build # 核心发版 Action: 自动创建 Version PR 或执行 npm 发布 - name: Create Release Pull Request or Publish uses: changesets/actionv1 with: publish: pnpm changeset publish version: pnpm changeset version commit: chore(release): version packages title: chore(release): version packages env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} NPM_TOKEN: ${{ secrets.NPM_AUTH_TOKEN }}落地成效发版零人肉干预版本号推导、依赖升级、Changelog 生成、Git Tag 与 npm 发布 100% 由 CI 机器接管变更日志颗粒度精准到每个 PR彻底消灭了传统发版时由管理员凭借记忆拼凑出来的空洞 Changelog多包依赖同步 0 差错Monorepo 内部子包版本号与依赖拓扑永远保持绝对一致。