{T}

版本管理工具对比与选择

概述

本文档对比了三个主流的 Node.js 版本管理工具:semantic-release、standard-version 和 Changesets,帮助开发者根据项目需求选择合适的工具。

快速对比

特性semantic-releasestandard-versionChangesets
自动化程度⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
学习曲线中等中等
Monorepo 支持⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
手动控制
CI/CD 集成⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
配置复杂度
社区活跃度
维护状态活跃维护模式活跃

详细对比

1. 工作流程

semantic-release

code
提交代码 → CI 触发 → 自动分析 → 自动发布 → 自动创建 Release
    ↓           ↓          ↓          ↓              ↓
 Developer  CI/CD     Analyze    Publish       GitHub Release

特点:

  • ✅ 完全自动化,无需人工干预
  • ✅ 适合持续发布流程
  • ❌ 发布时机不可控
  • ❌ 调试困难

standard-version

code
提交代码 → 手动触发 → 自动分析 → 手动推送 → 手动发布
    ↓           ↓          ↓          ↓           ↓
 Developer  Command   Analyze     Push       npm publish

特点:

  • ✅ 完全控制发布时机
  • ✅ 简单易用
  • ❌ 需要手动执行命令
  • ❌ 需要配置 CI/CD

Changesets

code
提交代码 → 创建变更集 → 合并 PR → 自动创建 Version PR → 合并后自动发布
    ↓           ↓          ↓              ↓                    ↓
 Developer  Changeset  Merge PR    Version PR            Auto Publish

特点:

  • ✅ 变更可追溯
  • ✅ 支持 Monorepo
  • ✅ 平衡自动化与控制
  • ❌ 需要维护变更集文件

2. 版本计算方式

semantic-release

基于提交信息自动计算:

code
feat: add feature    → 1.0.0 → 1.1.0 (Minor)
fix: fix bug         → 1.0.0 → 1.0.1 (Patch)
feat!: breaking      → 1.0.0 → 2.0.0 (Major)

standard-version

基于提交信息自动计算:

code
feat: add feature    → 1.0.0 → 1.1.0 (Minor)
fix: fix bug         → 1.0.0 → 1.0.1 (Patch)
BREAKING CHANGE      → 1.0.0 → 2.0.0 (Major)

Changesets

基于变更集文件手动指定:

markdown
---
"package-name": minor
---

描述信息

3. Monorepo 支持

semantic-release

javascript
// 需要额外配置
plugins: [
  ['@semantic-release/exec', {
    prepareCmd: 'lerna version ${nextRelease.version}',
    publishCmd: 'lerna publish from-package'
  }]
]

评分:⭐⭐⭐

standard-version

bash
# 需要在每个包中单独运行
cd packages/core
npx standard-version

评分:⭐⭐

Changesets

json
{
  "fixed": [["@myorg/ui", "@myorg/theme"]],
  "linked": [["@myorg/core", "@myorg/utils"]]
}

评分:⭐⭐⭐⭐⭐(专为 Monorepo 设计)

4. CHANGELOG 生成

semantic-release

  • 自动生成,无需配置
  • 支持自定义格式
  • 需要安装 @semantic-release/changelog 插件

standard-version

  • 自动生成,开箱即用
  • 支持自定义模板
  • 格式统一规范

Changesets

  • 自动生成,基于变更集
  • 支持自定义生成器
  • 内容更详细可控

5. CI/CD 集成

semantic-release

yaml
# GitHub Actions
- run: npx semantic-release
  env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

特点:原生支持,配置简单

standard-version

yaml
# GitHub Actions
- run: npx standard-version
- run: git push --follow-tags origin main
- run: npm publish

特点:需要额外配置发布步骤

Changesets

yaml
# GitHub Actions
- uses: changesets/action@v1
  with:
    publish: pnpm release

特点:官方 Action,配置简单

使用场景对比

semantic-release 适用场景

推荐使用:

  • 开源项目,需要持续发布
  • 单包项目,发布频率高
  • 团队规范统一,提交信息规范严格
  • 需要 GitHub Release 自动化

不推荐使用:

  • Monorepo 项目
  • 需要精确控制发布时机
  • 提交信息不规范的项目
  • 私有仓库,发布流程特殊

standard-version 适用场景

推荐使用:

  • 小型项目,发布频率低
  • 需要手动控制发布时机
  • 团队规模小,流程简单
  • 学习成本低的项目

不推荐使用:

  • Monorepo 项目
  • 需要完全自动化发布
  • 大型团队,发布频繁

Changesets 适用场景

推荐使用:

  • Monorepo 项目(强烈推荐)
  • 多包项目,需要协调版本
  • 需要变更追踪和审查
  • 平衡自动化与控制

不推荐使用:

  • 单包小型项目(过度工程)
  • 不需要 Monorepo 功能
  • 团队不接受维护变更集文件

决策树

code
开始选择
    ↓
是否是 Monorepo 项目?
    ├─ 是 → 使用 Changesets
    └─ 否 → 需要完全自动化发布?
              ├─ 是 → 使用 semantic-release
              └─ 否 → 需要手动控制发布时机?
                        ├─ 是 → 使用 standard-version
                        └─ 否 → 使用 semantic-release

迁移指南

从 standard-version 迁移到 semantic-release

1. 安装依赖

bash
pnpm add semantic-release @semantic-release/changelog @semantic-release/git -D
pnpm remove standard-version

2. 创建配置文件

javascript
// .releaserc.js
module.exports = {
  branches: ['main'],
  plugins: [
    '@semantic-release/commit-analyzer',
    '@semantic-release/release-notes-generator',
    '@semantic-release/changelog',
    '@semantic-release/npm',
    '@semantic-release/git',
    '@semantic-release/github'
  ]
}

3. 更新 CI 配置

yaml
# 删除手动发布步骤,替换为
- run: npx semantic-release
  env:
    GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
    NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

4. 迁移 CHANGELOG

保留现有 CHANGELOG.md,semantic-release 会在顶部追加新版本。

从 semantic-release 迁移到 Changesets

1. 安装依赖

bash
pnpm add @changesets/cli -D
pnpm remove semantic-release @semantic-release/*

2. 初始化

bash
npx changeset init

3. 配置

json
// .changeset/config.json
{
  "access": "public",
  "baseBranch": "main"
}

4. 更新工作流

bash
# 开发流程
npx changeset          # 创建变更集
git add .changeset/
git commit -m "feat: add feature"

# 发布流程
npx changeset version  # 更新版本
npx changeset publish  # 发布

从 standard-version 迁移到 Changesets

1. 安装依赖

bash
pnpm add @changesets/cli -D
pnpm remove standard-version

2. 初始化

bash
npx changeset init

3. 调整工作流

主要变化:

  • 从基于提交信息改为基于变更集文件
  • 需要为每个变更创建变更集文件
  • 支持更细粒度的版本控制

最佳实践总结

通用最佳实践

  1. 使用 Conventional Commits 规范

    bash
    feat: add feature
    fix: fix bug
    docs: update docs
  2. 保护主分支

    • 禁止直接推送到 main
    • 通过 PR 合并代码
  3. 配置 CI/CD

    • 自动运行测试
    • 自动发布
  4. 维护 CHANGELOG

    • 保持格式统一
    • 及时更新

semantic-release 最佳实践

javascript
// 1. 使用完整插件链
plugins: [
  '@semantic-release/commit-analyzer',
  '@semantic-release/release-notes-generator',
  '@semantic-release/changelog',
  '@semantic-release/npm',
  '@semantic-release/git',
  '@semantic-release/github'
]

// 2. 配置分支策略
branches: [
  'main',
  { name: 'beta', prerelease: true },
  { name: 'alpha', prerelease: true }
]

// 3. 使用 dry-run 验证
npx semantic-release --dry-run

standard-version 最佳实践

javascript
// 1. 配置提交类型
types: [
  { type: 'feat', section: 'Features' },
  { type: 'fix', section: 'Bug Fixes' }
]

// 2. 使用 npm scripts
{
  "release": "standard-version",
  "release:minor": "standard-version --release-as minor"
}

// 3. 配合 husky 和 commitlint
// 强制规范提交信息

Changesets 最佳实践

json
// 1. 配置 Monorepo 策略
{
  "fixed": [["@myorg/ui", "@myorg/theme"]],
  "linked": [["@myorg/core", "@myorg/utils"]],
  "ignore": ["@myorg/docs"]
}

// 2. 使用 GitHub Action 自动化
// 3. 每个变更创建变更集
// 4. 详细描述 breaking changes

常见问题

1. 如何选择工具?

简单决策:

  • Monorepo → Changesets
  • 需要全自动化 → semantic-release
  • 需要手动控制 → standard-version

2. 可以同时使用多个工具吗?

不推荐。 每个工具都有自己的版本管理逻辑,同时使用会导致冲突。

3. 如何处理历史版本?

semantic-release 和 standard-version:

  • 保留现有 CHANGELOG
  • 工具会自动追加新版本

Changesets:

  • 手动迁移 CHANGELOG
  • 从迁移后的版本开始使用

4. 私有仓库如何使用?

semantic-release:

javascript
{
  plugins: [
    '@semantic-release/commit-analyzer',
    '@semantic-release/release-notes-generator',
    '@semantic-release/changelog',
    '@semantic-release/npm',
    '@semantic-release/git'
  ]
}

standard-version: 正常使用,无需特殊配置。

Changesets:

json
{
  "access": "restricted"
}

5. 如何处理回滚?

所有工具都建议:

  1. 使用 npm deprecate 标记问题版本
  2. 删除 Git 标签
  3. 修复问题后重新发布

总结

选择建议

项目类型推荐工具理由
Monorepo 项目Changesets专为 Monorepo 设计,支持多包管理
开源单包项目semantic-release全自动化,适合持续发布
小型私有项目standard-version简单易用,手动控制
企业级项目Changesets变更可追溯,流程可控

学习路径

code
初学者 → standard-version(学习基础概念)
   ↓
进阶 → semantic-release(掌握自动化)
   ↓
高级 → Changesets(精通 Monorepo)

最终建议

  1. 新项目: 直接选择 Changesets(功能最全面)
  2. 现有项目: 根据实际需求评估是否迁移
  3. 团队接受度: 选择团队最容易接受的工具
  4. 长期维护: 优先选择活跃维护的工具

记住:没有最好的工具,只有最适合的工具。 根据项目特点、团队规模和发布频率选择合适的版本管理工具。