Changesets v3 面向 JavaScript monorepo 调整了三个关键环节:CLI 经过重构,安装体积缩小约 88%,软件包改为纯 ESM,同时 peer dependent 的版本更新策略改为补丁版本。对维护组件库、插件体系或多包 SDK 的团队来说,这不只是一次依赖升级——发布计划和 CI 环境都需要重新验证。
Peer dependent 为什么需要补丁版本
Changesets 的核心职责并没有改变:贡献者通过 changeset 文件声明“哪个包发生了什么变化,以及应该如何升级版本”,维护者再统一生成版本和 changelog。
v3 重点改善了 peer dependency 场景。假设工作区包含两个包:
@demo/core:核心运行时@demo/adapter:通过peerDependencies接入核心运行时
可以这样组织包清单:
{
"name": "@demo/adapter",
"version": "1.4.0",
"peerDependencies": {
"@demo/core": "^2.0.0"
}
}
当 @demo/core 发布变化时,adapter 即使没有直接打包 core,也可能需要产生一个新的发布版本,以便下游用户看到新的兼容状态和 changelog。v3 将这类 peer dependent 的联动升级处理为 patch,而不是施加更激进的版本影响。这能减少无意义的大版本升级,也是对长期使用反馈的回应。
但要注意:补丁升级并不会自动修复不兼容的 peer 范围。 如果 core 从 2.x 升到 3.0.0,上面的 ^2.0.0 依然不接受新版本。维护者仍需明确修改范围,例如:
{
"peerDependencies": {
"@demo/core": "^2.0.0 || ^3.0.0"
}
}
是否真的兼容两个主版本,必须由测试证明,不能仅靠放宽版本字符串。
纯 ESM 会影响哪些地方
Changesets v3 只发布 ESM。单纯通过命令行运行 changeset 的项目通常受影响较小,但以下位置值得检查:
- 使用
require()加载 Changesets 相关模块的内部脚本; - 运行在旧 Node.js 环境中的发布流水线;
- 假设依赖提供 CommonJS 入口的自定义工具;
- Jest、Node 或 bundler 中尚未正确处理 ESM 的脚本。
如果仓库脚本仍是 CommonJS,不要继续这样加载纯 ESM 包:
// CommonJS 中不再适合直接这样做
const changesetsModule = require("some-changesets-module");
可以把调用脚本迁移为 .mjs,或者让所在包使用 ESM:
{
"name": "release-tools",
"private": true,
"type": "module",
"scripts": {
"release:status": "changeset status"
}
}
如果暂时不能整体迁移,也可以在 CommonJS 脚本中使用动态导入。下面只是通用迁移形式,实际模块名和导出项应按项目所调用的 Changesets API 调整:
async function main() {
const module = await import("some-changesets-module");
console.log(Object.keys(module));
}
main().catch((error) => {
console.error(error);
process.exitCode = 1;
});
安装体积缩小约 88% 对 CI 和临时开发环境尤其有价值,不过实际节省量会受到 pnpm、npm 或 Yarn 的缓存、去重和全局存储机制影响。不要把包级体积降幅直接等同于流水线耗时降幅。
在 pnpm monorepo 中完成一次可回滚升级
下面是一套可以直接改造的升级流程。假设仓库已经使用 pnpm,并且默认分支为 main。
# 建议先创建独立分支
GitBranch="chore/upgrade-changesets-v3"
git switch -c "$GitBranch"
# 确认当前运行环境,避免把 ESM 问题误判为 Changesets 问题
node --version
pnpm --version
# 升级 CLI
pnpm add -Dw @changesets/cli@^3
# 检查 Changesets 能否读取现有配置和变更文件
pnpm exec changeset --help
pnpm exec changeset status
# 查看依赖树和锁文件变化
git diff -- package.json pnpm-lock.yaml .changeset
# 执行工作区测试与构建
pnpm -r test
pnpm -r build
如果项目此前没有使用 Changesets,可以初始化一个最小配置:
pnpm add -Dw @changesets/cli@^3
pnpm exec changeset init
随后创建一次发布声明:
pnpm exec changeset
该命令会交互式询问受影响的软件包、版本级别和变更说明,并在 .changeset/ 下生成 Markdown 文件。文件可以类似这样:
---
"@demo/core": patch
---
修复初始化阶段重复注册插件的问题。
在准备发布时,可以先提交一个只包含版本和 changelog 变化的预览分支:
pnpm exec changeset status
pnpm exec changeset version
pnpm install --lockfile-only
git diff
changeset version 会修改仓库文件,因此不要直接在未清理的工作区或正式发布分支上试跑。先创建临时分支,检查 peer dependent 是否得到预期的 patch,以及 peer 范围是否仍然正确。
配置迁移不要靠猜
来源摘要明确指出升级需要配置更新,但没有给出所有配置键的迁移细节。安全做法是让 v3 生成一份干净配置,再与现有配置逐项比较,而不是照搬旧示例。
可以在临时目录中执行:
TempDir="$(mktemp -d)"
cd "$TempDir"
printf '{"name":"changesets-v3-config-check","private":true}\n' > package.json
corepack enable
pnpm add -D @changesets/cli@^3
pnpm exec changeset init
cat .changeset/config.json
然后重点核对:
- 默认分支名称是否正确;
- changelog 生成器是否仍可加载;
- internal dependency 与 peer dependency 策略是否符合仓库预期;
fixed、linked、ignore等包分组是否被保留;- CI 中调用的命令和参数是否仍有效。
生成的临时配置只用于比较。不要覆盖生产仓库中的 .changeset/config.json,除非已经理解每个差异。
升级前后的检查清单
Changesets v3 更适合希望降低发布工具负担、同时改善 peer dependency 版本传播的 monorepo。不过,纯 ESM 和新的依赖升级语义都意味着它不应作为普通补丁依赖静默合并。
建议在合并前完成以下检查:
- 固定并记录 CI 使用的 Node.js 版本;
- 搜索仓库中的
require()和 Changesets 编程式调用; - 用真实 changeset 演练一次
status与version; - 检查 peer dependent 的 patch 是否符合发布策略;
- 对发生主版本变化的 peer dependency 手动审查版本范围;
- 比较安装大小、缓存命中率和流水线耗时,而不只看宣传数字;
- 保留升级前的锁文件,确保出现问题时可以快速回滚。
最稳妥的采用方式,是先选择一个包较少的 monorepo 或非关键发布分支试运行。确认生成的版本、changelog 和发布包内容都符合预期后,再推广到主要仓库。