为什么要用Monorepo
让关联仓库之间的修改变得容易
当一次Feature开发或者bug fix横跨多个git仓库的时候,你可能会想为什么不把它们放在一个仓库。
放到一个仓库后
于是你把多个package放在了同一个仓库,这时你发现:
新的问题
-
依赖重复安装问题
-
包之间引用问题,如何link
-
发布问题
-
怎么知道哪些包有改动?
-
这些改动是否都需要发版?
-
发包时的changelog怎么办
-
需要发版的包新的版本号谁来更新,版本号怎么处理?
major? minor? patch?
-
发包需要机械地重复执行下面的命令吗?
-
cd xxx
-
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主要能力:
- 生成新版本。
- lerna-changelog只能生成一套changelog,所有包都一样
- 一键发布所有包
changesets主要能力:
- 每个包分别生成新版本。
- 分别生成changelog
- 一键发布
changesets相比于lerna最关键的地方在于更灵活和更细粒度的控制每个package。
总结
所以Monorepo常见的解决方案都是Lerna/changesets + yarn/pnpm workspace,他们分别解决了不同的问题。
changesets大概工作流程
-
Add the changeset tool。初始化,生成.changesets文件夹
-
Adding changesets,每个changeset要记录的信息包含:
- 修改了哪些包
- 每个包的版本类型(following semver )
- 每个包的change information(changelog)
这些信息会生成文件放在.changesets目录下,可以积攒多个changesets,等到发布的时候同时发布
-
Versioning and publishing,生成版本并发布。此时会消耗所有的changesets并根据其中信息来生成版本和changelog