Changesets v3 升级指南:Peer 依赖补丁发布、纯 ESM 与更轻的安装体积

2026-09-22 16 预计阅读时间: 1 分钟
来源: infoq.com AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:9 分钟

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 策略是否符合仓库预期;
  • fixedlinkedignore 等包分组是否被保留;
  • CI 中调用的命令和参数是否仍有效。

生成的临时配置只用于比较。不要覆盖生产仓库中的 .changeset/config.json,除非已经理解每个差异。

升级前后的检查清单

Changesets v3 更适合希望降低发布工具负担、同时改善 peer dependency 版本传播的 monorepo。不过,纯 ESM 和新的依赖升级语义都意味着它不应作为普通补丁依赖静默合并。

建议在合并前完成以下检查:

  • 固定并记录 CI 使用的 Node.js 版本;
  • 搜索仓库中的 require() 和 Changesets 编程式调用;
  • 用真实 changeset 演练一次 statusversion
  • 检查 peer dependent 的 patch 是否符合发布策略;
  • 对发生主版本变化的 peer dependency 手动审查版本范围;
  • 比较安装大小、缓存命中率和流水线耗时,而不只看宣传数字;
  • 保留升级前的锁文件,确保出现问题时可以快速回滚。

最稳妥的采用方式,是先选择一个包较少的 monorepo 或非关键发布分支试运行。确认生成的版本、changelog 和发布包内容都符合预期后,再推广到主要仓库。


相关推荐