◆

Lerna init 初始化 monorepo 项目

2023-02-02 01:370

lerna 解决什么问题

一个仓库里放多个 npm 包(monorepo)之后会碰到几件麻烦事:包之间互相依赖,改了 A 要让 B 立刻用上最新的;发版时要按依赖顺序逐个 publish;每个包的版本号还得对齐。手工做这些既慢又容易漏。lerna 就是把这套流程自动化的工具,它负责识别工作区里有哪些包、理清它们的依赖拓扑,然后批量执行命令、批量发版。

现在 pnpm workspace、yarn workspaces 已经接管了「本地包互相链接」这部分职责,所以实践中常见的组合是 pnpm 管依赖、lerna 只管版本和发布。

初始化

在空目录里执行下面这条命令,lerna 会生成 lerna.json 配置文件、创建 packages/ 目录,并在 package.json 里补上必要的字段:

lerna init --independent 初始化项目。

关键在于 --independent 这个参数,它决定了版本管理模式,选错了后面改起来很别扭。

两种版本模式的区别

固定模式(默认,不加 --independent):所有包共用一个版本号,记录在 lerna.json 的 version 字段里。发版时只要有任何一个包变了,全部包一起升到同一个新版本,哪怕某些包代码一字未动。Babel 用的就是这套,好处是用户不用操心版本搭配,看到同一个版本号就知道能配套使用;坏处是版本号增长很快,changelog 里会出现大量「本次无实际变更」的包。

独立模式(--independent):lerna.json 里的 version 会被写成 independent,每个包各自维护自己的版本号。发版时 lerna 检测出哪些包有改动,只对这些包提示版本号,改动小的包停在低版本不动。适合各个包相对独立、使用者也是分开引用的场景。

我一般选独立模式。理由是包之间耦合度往常没有想象中那么高,工具包升个补丁没必要把整个仓库的版本都往上抬。真正需要固定模式的情况是这些包必须成套使用、单独装某一个没有意义。

常用命令

初始化之后最常用的是这几条:

# 查看工作区里的所有包
lerna list

# 只看相比上次发版有改动的包
lerna changed

# 在所有包里执行某个 npm script,按依赖顺序
lerna run build

# 交互式确定各包新版本,打 tag 并生成 changelog
lerna version

# 把有变更的包发到 registry
lerna publish

lerna version 和 lerna publish 是分开的两步,前者只处理版本号、git tag 和 commit,后者才真正推包。刚开始接触时容易以为 publish 会顺带做版本管理——实际上 lerna publish 默认会先跑一遍 version 流程,但显式分开执行更可控,特别是在 CI 里,可以本地 version、CI 里 publish。

发版前建议先 lerna changed 确认一下改动范围。这条命令依据的是上一个 git tag 之后的提交记录,如果发现结果不对,通常是 tag 没打或者没有 fetch 到远端的 tag。

💬留言板0

还没有留言,来发表第一条吧~

PAGE LOAD / LIVELerna init 初始化 monorepo 项目加载中