WEBKT

实战进阶:Monorepo 环境下使用 Changesets 自动化管理语义化版本与发布全流程

3 0 0 0

在现代前端工程化中,Monorepo(单仓多包)架构已成为大型项目的标配。然而,随着包数量的增加,如何优雅地管理数十个子包的语义化版本(SemVer)、生成更具可读性的 Changelog,以及处理复杂的包间依赖更新,成为了开发者不得不面对的挑战。

传统的 Lerna 虽然经典,但在大型项目中往往显得过于笨重,且其维护状态一度陷入停滞。此时,Changesets 以其“去中心化”、“开发者友好”以及“与 CI/CD 高度集成”的特性,成为了当前 pnpm 或 Yarn Workspaces 架构下的首选方案。

一、 为什么选择 Changesets?

  1. 非侵入性:在开发阶段只需运行一个简单的命令记录变更。
  2. 依赖联动:如果 A 包依赖 B 包,当 B 版本升级时,Changesets 会自动识别并提示 A 包是否需要跟随升级。
  3. 高度可定制:支持自定义 Changelog 生成逻辑。
  4. CI 友好:官方提供的 GitHub Actions 能够实现从合并 PR 到发布 NPM 的全自动化。

二、 核心工作流拆解

1. 初始化配置

在项目根目录下安装依赖并初始化:

pnpm add -W @changesets/cli
npx changeset init

执行后,根目录会生成 .changeset 文件夹,其中包含 config.json。这是 Changesets 的大脑。

关键配置项:

  • access: 默认为 restricted,如果是开源项目需改为 public
  • baseBranch: 主分支名(如 mainmaster)。
  • 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

这个命令会执行以下操作:

  1. 消耗掉 .changeset 下的所有临时 .md 文件。
  2. 根据定义的语义化版本规则,自动更新受影响子包的 package.json
  3. 为每个包自动生成或更新 CHANGELOG.md
  4. 更新 Monorepo 内部互相引用的版本号(如 workspace:* 自动更新为具体数值)。

4. 发布阶段:推送 NPM(The "Publish" Step)

npx changeset publish

该命令会检查本地 package.json 与远端仓库的版本差异,仅发布未曾发布的版本。


三、 进阶:集成 GitHub Actions 实现全自动化

Changesets 的强大之处在于配合 GitHub Actions。我们可以设定这样一个流程:

  1. 开发者提交代码(包含 changeset 记录文件)。
  2. 代码合并到 main 分支后,Action 运行并自动创建一个名为 "Version Packages" 的 Pull Request
  3. 这个 PR 已经帮你运行过 changeset version,包含版本号和 Changelog 的更新。
  4. 一旦管理员合并这个 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 }}

四、 避坑指南与最佳实践

  1. Pre-release 模式:如果你需要发布测试版(如 alphabeta),可以使用 npx changeset pre enter alpha。此时所有的版本更新都会带上后缀,直到执行 exit
  2. Changelog 定制:默认的 Changelog 比较简单。如果需要包含 GitHub 用户名、PR 链接等信息,推荐安装 @changesets/changelog-github 并在配置中启用。
  3. 不要手动改版本号:在 Changesets 体系下,严禁手动修改 package.json 里的 version 字段,否则会导致版本对齐逻辑混乱。
  4. 原子化提交:尽量保证一个变更记录对应一个功能点,避免在一个 changeset 文件里描述太多不相关的东西。

总结

Changesets 将 Monorepo 繁琐的版本管理工作转化为简单的交互式命令和自动化脚本。对于团队协作而言,它最大的价值在于强制规范化了变更信息的收集过程,让每一行代码的变更都“有迹可循”。如果你的 Monorepo 还在为发布版本而苦恼,那么 Changesets 绝对值得一试。

码农架构师 MonorepoChangesets版本管理

评论点评