Sparkee是一个类似lerna的monorepo管理工具,但又有很多不同,本文将详细介绍本人开发sparkee的初衷以及该工具的具体使用场景。
为什么要造轮子
造轮子的初衷无非无非就是现有的工具不好用或不能满足自己的项目场景。在我自己的monorepo项目中有以下几点是lerna等monorepo工具无法解决的:
pnpm局限性
项目使用pnpm自带的monorepo功能进行依赖管理和同仓多项目管理,但pnpm的版本管理和发布功能却十分鸡肋,无法查看当前monorepo下package的版本和相互依赖关系,且发布只有pnpm publish发布全部package或使用--filter指定package发布,至于版本自增、changelog等发布工作流自己配合changesets和Rush使用。
lerna局限性
lerna在发布工作流就做的很好,上述pnpm的局限性貌似可以解决,但在项目具体使用中发现以下问题:
-
lerna的monorepo管理方式是统一开发、统一发布,比较典型的是babel这个大型monorepo,每个package的依赖关系极强,因此一个release发布需要涉及全部package的发布。但在我的实际项目中,每个package确实存在依赖关系,但一旦只有一个package发生变动,这个package发布时我是不希望其余package只是修改版本然后发布一次,相比我更希望支持pnpm --filter <package> publish的方式,很遗憾lerna不支持这个特性。 -
lerna不支持workspace协议。pnpm的monorepo管理支持使用workspace协议,在package.json中使用"foo": "workspace:*"的方式调用package,因此在执行pnpm publish时pnpm会自动修改package的当前版本号,无需担心workspace关键字会发布到release版本的package.json中。遗憾的是lerna已经停止新功能迭代,无法对workspace协议进行支持,在lerna-lite 号称可以支持workspace协议协议,兼容lerna命令,但在具体使用时发现lerna-lite依然会在发布时强制把package的本地package.json文件里的workspace关键字去掉再进行发布,因此lerna-lite也不能很好的兼容workspace协议发布。
此时sparkee就是基于pnpm publish保留workspace协议但又能很好的支持lerna发布工作流而开发的monorepo版本管理工具
sparkee特性
-
相比
lerna复杂而且冗长的命令,sparkee命令很简单,目前只有三个命令:sparkee init,sparkee info和sparkee publish -
支持
workspace协议,执行sparkee publish其实内部调用的是pnpm publish,因此无需担心项目内workspace被影响 -
发布支持
版本自增、自动提交tag、changelog自动生成,符合lerna标准发布工作流,弥补pnpm发布管理短板 -
支持单个
package发布 -
支持
package版本查看以及树状依赖关系图
sparkee支持的项目结构
sparkee需要在标准monorepo项目结构下工作,即package需要统一放在packages下,每个package维护自己的package.json:
your-repo/
package.json
packages/
package-1/
package.json
package-2/
package.json
这里需要注意的是
sparkee将package.json内的name作为package的名称,而不是目录名,这一点和pnpm规则是一样的
这里我展示具体demo的项目结构:
pnpm-monorepo
├── package.json
├── packages
├── pkg1
| └── package.json // name: @geocld/pkg1
└── pkg2
└── package.json // name: @geocld/pkg2
安装
sparkee支持全局安装或在项目内安装使用:
$ npm i sparkee -g
$ npm i sparkee --save-dev
或者通过pnpm add将sparkee安装在最外层:
$ pnpm add sparkee -w
安装完成后可以通过sparkee或spk执行sparkee
安装在项目内使用
npx sparkee或npx spk

sparkee init
sparkee init会初始化当前monorepo,init过程用户指定选择管理当前packages下的package,或者管理全部:
$ npx sparkee init

初始化完成后项目根目录会生成一个spark.json,内容即刚才选择需要管理的模块:
// spark.json
{
"packages": [
"@geocld/pkg1",
"@geocld/pkg2"
]
}
sparkee info
sparkee info可以查看当前packages的版本信息,可选项--tree展示packages的依赖树关系。
$ sparkee info <--tree>
info

info -- tree

sparkee publish
sparkee publish是sparkee的核心,其遵循了模块发布的标准工作流。
执行sparkee publish时,其内部主要做了以下工作:
- 通过比较最近一次的
tag检测到最近一次提交变动的项目(src文件夹和package.json),如果没有发布过tag则以第一次commit做比较 - 选择需要发布的模块,可以发布单个或多个模块
- 自动更新
package下package.json的版本号 - 通过
conventional-changelog在选定发布的package中生成changelog,注意changelog需要git commit符合Angular提交规范,否则得到的changelog可能是空的 - 自动依次执行
git Commit、git tag、git push - 通过
pnpm进行发布
完整的sparkee工作流如下:

demo:

总结
可以说Sparkee是为了完善pnpm发布而开发的版本发布工具,如果你的项目使用了pnpm,同时希望得到有别于lerna的版本发布方式,那么可以试一下sparkee。如果你对这个项目感兴趣,可以随时对本项目发起pr以完善sparkee的功能和使用体验。
(完)