【认知篇】一文说透Monorepo,Changesets和Lerna都有什么用

2,303 阅读2分钟

为什么要用Monorepo

让关联仓库之间的修改变得容易

当一次Feature开发或者bug fix横跨多个git仓库的时候,你可能会想为什么不把它们放在一个仓库。

放到一个仓库后

于是你把多个package放在了同一个仓库,这时你发现:

新的问题

  1. 依赖重复安装问题

  2. 包之间引用问题,如何link

  3. 发布问题

    1. 怎么知道哪些包有改动?

    2. 这些改动是否都需要发版?

    3. 发包时的changelog怎么办

    4. 需要发版的包新的版本号谁来更新,版本号怎么处理?

      major? minor? patch?

    5. 发包需要机械地重复执行下面的命令吗?

      1. cd xxx

      2. npm publish

如何解决

1. workspace

workspace可以解决上述问题1、2。

以pnpm workspace为例,添加workspace配置文件pnpm-workspace.ymal

packages:
  - "packages/**"

此时pnpm会帮你提取公共依赖安装到根目录,同时会自动将版本匹配的package给link。例如packageA中import packageB,此时就会直接import packageB目录下的代码而不是从npm仓库下载。

2. 版本管理工具:Lerna/changesets

如果一个git repo中只包含一个项目,那么package距离上一次发布过程中所有的修改(changelog)都可以从git commit的信息中获取到,进一步可以借助semantic-release根据这些信息生成语义化版本并发布。

到了多包场景(一个repo中包含了很多package),每次要发布很多包,每个包都需要自己的版本和changelog,此时changelog不能直接用commit信息,因为repo只有一套commit代表了所有包的改动,所以就需要一个工具来分别记录每个包的修改。

Lerna和changesets都是为了解决这些发布问题而产生的工具。

Lerna主要能力:

  1. 生成新版本。
  2. lerna-changelog只能生成一套changelog,所有包都一样
  3. 一键发布所有包

changesets主要能力:

  1. 每个包分别生成新版本。
  2. 分别生成changelog
  3. 一键发布

changesets相比于lerna最关键的地方在于更灵活和更细粒度的控制每个package。

总结

所以Monorepo常见的解决方案都是Lerna/changesets + yarn/pnpm workspace,他们分别解决了不同的问题。

changesets大概工作流程

  1. Add the changeset tool。初始化,生成.changesets文件夹

  2. Adding changesets,每个changeset要记录的信息包含:

    1. 修改了哪些包
    2. 每个包的版本类型(following semver )
    3. 每个包的change information(changelog)

    这些信息会生成文件放在.changesets目录下,可以积攒多个changesets,等到发布的时候同时发布

  3. Versioning and publishing,生成版本并发布。此时会消耗所有的changesets并根据其中信息来生成版本和changelog