大家好,我是 一步梅。
做前端工程化这些年,我最怕两件事:一是发版时把依赖包版本改错,二是写更新日志(Changelog)时靠翻最近一个月的 Git Commit 凭空回忆。
在单仓库(Single-repo)下,semantic-release 等工具确实好用;但一旦项目演进到多包管理(Monorepo)模式,涉及相互依赖、跨包改动时,自动化发版和维护文档就容易陷入混乱。
今天这篇文章,我就分步骤给大家讲明白:如何利用 Changesets 搭建一套清晰、不易出错的 Monorepo 语义化发版(SemVer)与 Changelog 自动化生成工作流。
一、 痛点与选型:为什么是 Changesets?
在 Monorepo 项目中,传统的提交触发发版方案常常面临几个具体问题:
- 改动零散: 一个功能 PR 可能改动了
core和ui两个包,但只应该给ui发个 Minor,给core发个 Patch。 - 文档滞后: 传统的规范提交(Conventional Commits)颗粒度太细,直接拿 Commit 拼出来的 Changelog 往往充斥着
fix: typo、chore: lint,对真正看文档的使用者毫无价值。 - 依赖联动发版:
pkg-b依赖了pkg-a,pkg-a发版后,pkg-b是否需要升级?手动算很容易算漏。
Changesets 的设计思路非常直观:它不依赖抓取 Commit 记录,而是把**“写变更说明”**这件事变成开发过程中的一个文件记录动作。
- 开发者改完代码,运行命令生成一个临时的 Markdown 记录文件。
- 这个文件随代码一起提 PR 并合并。
- 发版时,工具统一消耗这些文件,精准计算所有包的版本跳级,生成规范的
CHANGELOG.md并清理记录。
二、 环境准备与初始化
假设我们使用的是目前最常见的 pnpm workspace 架构。
1. 安装依赖
在仓库根目录下安装:
pnpm add -Dw @changesets/cli
2. 初始化配置
在根目录执行初始化命令:
pnpm changeset init
执行后,仓库根目录会出现一个 .changeset 文件夹,核心配置文件是 .changeset/config.json。
3. 核心配置解析
针对典型的 Monorepo 场景,推荐的起步配置如下:
{
"$schema": "https://unpkg.com/@changesets/config/schema.json",
"changelog": "@changesets/cli/changelog",
"commit": false,
"fixed": [],
"linked": [],
"access": "public",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": []
}
access:如果你发布的是开源包且组织带命名空间(如@my-org/utils),请设为"public",否则发布私有包时需要鉴权。updateInternalDependencies:设置为"patch"。这意味着如果 A 包升级了,依赖 A 的 B 包会自动升一个 Patch 版本并更新对应的依赖版本号,极大减少人为失误。baseBranch:你的主分支名称(通常为main或master)。
三、 日常开发流:如何记录一次变更?
假设今天你在 packages/button 中修了一个样式 Bug,并在 packages/core 中加了一个新工具函数。
步骤 1:触发交互式 CLI
代码写完后,在本地终端运行:
pnpm changeset
终端会出现交互式选择界面:
- 用空格键勾选本次受影响的包:
packages/button、packages/core。 - 选择版本跳级类型(Major / Minor / Patch):
- 对
button选择patch(修复缺陷)。 - 对
core选择minor(新增向后兼容的特性)。
- 对
- 输入本次变更的详细描述。
步骤 2:生成变更集文件
CLI 会在 .changeset 目录下生成一个随机命名的 Markdown 文件,例如 .changeset/blue-cats-dance.md。其内容如下:
---
"@my-org/button": patch
"@my-org/core": minor
---
- 修复了 Button 组件在禁用状态下的光标样式。
- 新增 `useDebounce` 工具函数,方便输入防抖。
梅的提示:这个 Markdown 文件就是未来的 Changelog 原型。它支持正常的 Markdown 语法,可以写得详细一点,把“对使用者的影响”讲明白,而不仅仅写一句 Commit 摘要。
接着,把这个 .md 文件随着你的业务代码一起 git commit 并提交 PR。
四、 版本提升与 Changelog 生成(本地演练)
当主分支积累了若干个合并进来的 changeset 文件后,就该发版了。整个发版分为两步:提版本(Version) 与 发布(Publish)。
1. 计算版本与更新文档
运行命令:
pnpm changeset version
这时候,Changesets 会做这几件事:
- 读取
.changeset/*.md中的所有指令。 - 更新对应包的
package.json中的version字段。 - 更新包与包之间的内部依赖版本。
- 在受影响包的目录下,自动生成或追加
CHANGELOG.md,把刚才记录的说明规整地放进去。 - 删除已经消耗掉的
.changeset/*.md文件。
生成出的 CHANGELOG.md 样例如下:
# @my-org/core
## 1.1.0
### Minor Changes
- 新增 `useDebounce` 工具函数,方便输入防抖。
---
# @my-org/button
## 1.0.1
### Patch Changes
- 修复了 Button 组件在禁用状态下的光标样式。
到这一步,版本号和文档全都是自动、对齐且精准的。
五、 进阶:接入 GitHub Actions 实现自动化闭环
手敲命令依然容易遗漏,最佳实践是利用官方提供的 GitHub Action(changesets/action)实现“全自动发版 PR”。
在仓库中添加 .github/workflows/release.yml:
name: Release
on:
push:
branches:
- main
concurrency: ${{ github.workflow }}-${{ github.ref }}
jobs:
release:
name: Release
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- name: Install pnpm
uses: pnpm/action-setup@v3
with:
version: 8
- name: Install Dependencies
run: pnpm install --frozen-lockfile
- name: Create Release Pull Request or Publish
id: changesets
uses: changesets/action@v1
with:
title: "chore: version packages"
commit: "chore: version packages"
publish: pnpm changeset publish
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
这套 CI 流程的精妙之处:
- 自动聚合发版 PR: 当你往
main分支合入代码后,Action 发现有未消耗的 changeset 文件,它不会立刻发布,而是会自动建一个名为chore: version packages的 PR。 - 所见即所得: 在这个 PR 里面,你可以清晰地预览到本次所有被更改的包、版本变动以及渲染好的
CHANGELOG.md。 - 合并即发布: 一旦团队负责人确认无误,将这个版本 PR 合并,CI 再次运行,识别出没有新的 changeset 文件,就会直接执行
publish逻辑,将包推到 NPM。
六、 总结
把前端文档和发版做好,核心不在于流程有多繁复,而在于把信息记录的动作前置到每一次代码提交流程中,同时把汇总计算的工作彻底交给自动化。
基于 Changesets 的方案,优势可以总结为三句话:
- 语义精准: 开发者在改代码时最清楚变更影响,当时记录最准确。
- 依赖无忧: 自动处理 Monorepo 内部包的依赖级联升级。
- 文档沉淀: 发版 PR 即是文档预览,合并即完成交付,不再依赖人工维护 Changelog。
工程化的本质是让人省心。把繁琐的机械劳动收敛到工具底层,开发者才能真正把精力留给业务架构与好代码。
License: CC BY-NC 4.0
Updated 13 hours ago
Was this article helpful? Give it a like.
0 comments


