Javascript is required
Changesets

是什么

流行的 monorepo 场景发包工具

Changesets 是一个用于 Monorepo 项目下版本以及 Changelog 文件管理的工具。目前一些比较火的 Monorepo 仓库都在使用该工具进行项目的发包例如 pnpm、mobx 等。

github 仓库为: https://github.com/changesets/changesets在 github 上有大约 7k 的 star。

changesets 是用于管理版本及变更日志的工具,专注多包管理。

您可以为 monorepo 中的每个包定义一组更改和更新。这些更改可能包括错误修复、新功能、性能改进或任何其他修改。

为什么

它解决了单一存储库中管理版本的复杂性,提供了简单而高效的解决方案。

帮助

 npx changeset --help    

  Organise your package versioning and publishing to make both contributors and maintainers happy

  Usage
    $ changeset [command]
  Commands
    init
    add [--empty] [--open]
    version [--ignore] [--snapshot <?name>] [--snapshot-prerelease-template <template>]
    publish [--tag <name>] [--otp <code>] [--no-git-tag]
    status [--since <branch>] [--verbose] [--output JSON_FILE.json]
    pre <enter|exit> <tag>
    tag

cli提供了这些命令

        flowchart LR

1["changesets"]
1 --> add
1 --> init
1 --> pre
1 --> publish
1 --> status
1 --> tag
1 --> version

      

Lerna 发包方案缺陷

  • ignoreChanges 不能做到文件的完全忽略,存在优先级问题
  • lerna version 根据 commit 以及 tag 更新出来的包版本不符合预期
  • 生成的 CHANGELOG 文件信息不完整
  • lifecycle scripts 经常命中一些用户自定义的 script(例如 publish 等)
  • CI 中自动化发包场景需要很高的定制成本
  • lerna 本身不支持 workspace 协议,导致基于 pnpm 开发的一些仓库无法使用

Changesets 工作流程介绍

changesets 主要关心 monorepo 项目下子项目版本的更新、changelog 文件生成、包的发布。一个 changeset 是个包含了在某个分支或者 commit 上改动信息的 md 文件,它会包含这样一些信息:

  • 需要发布的包
  • 包版本的更新层级(遵循 semver 规范)
  • CHANGELOG.md 信息

典型的工作流程包括

  1. 创建changesets

npx changeset 此命令将打开一个交互式提示,允许您选择已更改的包并指定更改的类型

版本类型

1. Patch. 例如 1.0.1 -> 1.0.2
2. Minor  例如 1.0.1 -> 1.1.0
3. Major  例如 1.0.1 -> 2.0.0
  1. 计算新版本

创建changesets后,下一步是确定每个包的新版本。

  1. 发布更新的包

通过命令npx changeset publish 发布到npm或私服。 它还为版本创建 Git 标签,使您可以轻松跟踪和引用它们

https://lirantal.com/blog/introducing-changesets-simplify-project-versioning-with-semantic-releases

安装

要开始使用changesets,您需要将其安装为开发依赖项。打开终端并导航到项目目录。运行以下命令以使用 npm 安装变更集

安装依赖

pnpm i @changesets/cli
"license": "ISC",
"devDependencies": {
"@changesets/cli": "^2.26.1",
❯ npx changeset init   
🦋  Thanks for choosing changesets to help manage your versioning and publishing
🦋  
🦋  You should be set up to start using changesets now!
🦋  
🦋  info We have added a `.changeset` folder, and a couple of files to help you out:
🦋  info - .changeset/README.md contains information about using changesets
🦋  info - .changeset/config.json is our default config

如何添加版本发布到 GitHub

npm install --save-dev @changesets/changelog-github

子命令

init

初始化必要的文件和目录

        flowchart LR
1["存储"]
1 --> .changeset
1 --> config.json

      
npx changeset init

🦋  Thanks for choosing changesets to help manage your versioning and publishing
🦋  
🦋  You should be set up to start using changesets now!
🦋  
🦋  info We have added a `.changeset` folder, and a couple of files to help you out:
🦋  info - .changeset/README.md contains information about using changesets
🦋  info - .changeset/config.json is our default config

该命令为初始化命令,通过执行 changeset init,可以在项目根目录下生成一个 .changeset 目录,里面会生成一个 changeset 的 config 文件

该命令原理相对简单,执行的时候通过 fs 将对应配置文件写到目录下就行,关于 config 中的具体配置描述可以参考https://github.com/changesets/changesets/blob/main/docs/config-file-options.md。init 初始化出来的为默认配置,一般不需要用户去做过多的修改。

注意:

{
    "$schema": "https://unpkg.com/@changesets/config@1.5.0/schema.json",
    "changelog": [
        "@changesets/changelog-github",// @changesets/changelog-github 是一个生成 changelog 的插件 
        {
            "repo": "xxx" // 改为你的 github 仓储
        }
    ],
    "commit": false,
    "linked": [],
    "access": "public",
    "baseBranch": "master",
    "updateInternalDependencies": "patch",
    "ignore": []
}

add

❯ npx changeset  add
🦋  Which packages would you like to include?◯ unchanged packages
  ◯ admin
  ◯ @cool-vue/layout
  ◯ @cool-vue/crud

add 在 changesets 中算得上比较关键的命令之一了,它会根据 monorepo 下的项目来生成一个 changeset 文件,里面会包含前面提到的 changeset 文件信息(更新包名称、版本层级、CHANGELOG 信息)。

会让我们选择本次 changeset 需要发布的包,这些包名都是 Monorepo 项目下的子包,changesets 内部通过 getPackages() 这一方法得到 Monorepo 项目下子项目信息

changesets 下面一个叫做 @manypkg/get-packages 的包。方法本质上是通过读 Monorepo 下所有子项目的 package.json 然后构建出一个依赖图出来,changesets 可以根据该结果得到需要进行发包流程的项目,可以说整个 changesets 项目本身都会基于底层这个方法来进行构建,有点类似于一般 Monorepo 工具中的 graph 构建。

demo

 npx changeset  add
🦋  What kind of change is this for @test/utils? (current version is 0.0.0) … 
 patch
  minor
  major

在软件开发中,"patch"、"minor"和"major"通常用来表示版本号的不同级别的更新

  • "patch"(补丁)表示对软件进行小的修复或改进,通常是修复一些bug、漏洞或进行一些小的优化,不会引入新的功能。
  • "minor"(次要)表示对软件进行一些较小的改进或增加一些新的功能,但仍保持向后兼容性,不会破坏现有的功能或接口。
  • "major"(主要)表示对软件进行重大的改进、重构或引入了不向后兼容的变化,可能会破坏现有的功能或接口。
  • pnpm changeset version:此命令会自动根据当前的变更类型(如 fixfeatchore 等)来确定要发布的版本类型。如果变更类型是 fix,则会选择补丁版本(patch),如果是 feat,则会选择次要版本(minor),其他类型则为主要版本(major)。
  • pnpm changeset version --type patch:此命令会强制选择补丁版本(patch)作为要发布的版本类型。
  • pnpm changeset version --type minor:此命令会强制选择次要版本(minor)作为要发布的版本类型。

version

version 这个命令这里可以当作 bump version 来理解,这里本质上做的工作是消耗 changeset 文件并且修改对应包版本以及依赖该包的包版本,同时会根据之前 changeset 文件里面的信息来生成对应的 CHANGELOG 信息。

执行后子包的版本号会增加。

此命令将根据您的changesets计算新版本并更新package.json受影响的包的文件。此外,它还会为版本创建新的 Git 标签。

publish

  tl-cli git:(main)  npx changeset publish --access publish
🦋  info npm info @taoya7/cleanup
🦋  info npm info @taoya7/commit-cli
🦋  info npm info @taoya7/i18n-cli
🦋  info npm info @taoya7/label-cli
🦋  info npm info @taoya7/cli-shebang
🦋  info npm info @taoya7/templates-cli
🦋  info npm info @taoya7/cli-ui
🦋  warn @taoya7/cleanup is not being published because version 1.0.11 is already published on npm
🦋  info @taoya7/commit-cli is being published because our local version (1.0.16) has not been published on npm
🦋  warn @taoya7/i18n-cli is not being published because version 1.0.11 is already published on npm
🦋  warn @taoya7/label-cli is not being published because version 1.0.12 is already published on npm
🦋  warn @taoya7/cli-shebang is not being published because version 1.0.11 is already published on npm
🦋  warn @taoya7/templates-cli is not being published because version 1.0.0 is already published on npm
🦋  warn @taoya7/cli-ui is not being published because version 1.0.11 is already published on npm
🦋  info Publishing "@taoya7/commit-cli" at "1.0.16"
🦋  success packages published successfully:
🦋  @taoya7/commit-cli@1.0.16
🦋  Creating git tag...
🦋  New tag:  @taoya7/commit-cli@1.0.16

包的发布

这里需要注意的是,版本的选择一共有三种类型,分别是 patchminormajor,严格遵循 semver 规范。

例子

 npx  changeset publish
🦋  info npm info @test/utils
🦋  info @test/utils is being published because our local version (0.0.1) has not been published on npm
🦋  info Publishing "@test/utils" at "0.0.1"
🦋  success packages published successfully:
🦋  @test/utils@0.0.1
🦋  Creating git tag...
🦋  New tag:  @test/utils@0.0.1

不提交某个包

如果你想在 Changesets 中选择性地提交某个包而不发布它,可以使用

--skip <packageName>

选项。这个选项允许你指定要跳过发布的特定包。

semver

常见的tag

名称功能
alpha是内部测试版,一般不向外部发布,会有很多Bug,一般只有测试人员使用
beta也是测试版,这个阶段的版本会一直加入新的功能。在Alpha版之后推出
rcRelease Candidate) 系统平台上就是发行候选版本。RC版不会再加入新的功能了,主要着重于除错
pnpm changeset pre enter beta

之后在此模式下的 changeset publish 均将默认走 beta 环境,下面在此模式下任意的进行你的开发

# 1-1 进行了一些开发...
# 1-2 提交变更集
pnpm changeset
# 1-3 提升版本
pnpm version-packages # changeset version
# 1-4 发包
pnpm release # pnpm build && pnpm changeset publish --registry=...
# 1-5 得到 1.0.0-beta.1

# 2-1 进行了一些开发...
# 2-2 提交变更集
pnpm changeset
# 2-3 提升版本
pnpm version-packages
# 2-4 发包
pnpm release
# 2-5 得到 1.0.0-beta.2

完成版本发布之后,退出 Prereleases 模式

$ pnpm changeset pre exit

参考

https://juejin.cn/post/7024827345059971080

https://lirantal.com/

semver规范

https://semver.org/