多工程管理方式 - lerna的使用

一、lerna是干什么用的

为什么叫lerna? lerna是希腊神兽九头蛇Lernaean Hydra的前几个字母,也间接形象的描述了多包管理的功能

简单来说:它优化了使用Git和NPM管理多包存储库的工作流,用来管理多个npm项目,处理每个项目相互之前引用关系,以及每个项目的发布管理。

一个lerna项目的结构大致如下:

my-lerna-repo/
  package.json
  packages/
    package-1/
      package.json
    package-2/
      package.json

二、什么时候使用lerna

假如我们有A、B、C三个npm项目,其中A要引用B,B要引用C,且A、B、C都可以单独被其他引用。这里考虑两个问题:
1、如何分别调试这几个项目呢?
2、这几个项目怎么发布才合理呢?

我们的答案可能是:
1、分别创建A、B、C三个项目,调试的时候使用npm link
2、每个项目分别发布,修改后,每个项目修改版本、打tag、依次push并publish

这样做确实可以打到目的,但是显然是个繁琐复杂而且容易出错的过程
首先,这样做需要每个开发者在本地link项目调试,耗时
其次,每次修改都要多个项目分别改版本、打tag、依次push并publish,耗力

这个时候就是lerna上场的时候了

三、如何使用lerna

1、全局安装

npm install lerna -g

2、项目初始化

从git仓库clone下来新建的项目目录如下:

my-lerna-demo
|--- .gitignore
|--- README.md

在根目录中执行命令lerna init就可以初始化项目了,此时目录如下:

my-lerna-demo
|--- packages # 包目录
|--- .gitignore
|--- lerna.json #lerna配置
|--- package.json
|--- README.md

在packages下添加自己的项目,也可以使用lerna create创建

my-lerna-repo/
  package.json
  packages/
    packageA/
      index.js
      package.json
    packageB/
      index.js
      package.json

3、配置lerna.json

更多配置见: GitHub - lerna/lerna: A tool for managing JavaScript projects with multiple packages.

4、初始化依赖:lerna bootstrap

执行lerna bootstrap,它做了下面四件事:

(1)intsall所有包的依赖
(2)执行所有包的link操作
(3)执行每个包的npm run prepublish命令
(4)执行每个包的npm run prepare命令

5、发布到npm:lerna publish

lerna publish做了一套npm标准的发布流程管理。

1、根据git提交记录对比包的变化,发布发生修改的包
2、发布版本号的规范提示
3、每个版本自动生成git tag,并提交master

四、lerna publish 及管理发布版本的两种方式

lerna publish工作流程

1、lerna publish 分为几种不同的场景去运行:

(1)lerna publish

发布自上次发布以来发生变化的包,执行lerna version + lerna publish from-git

(2)lerna publish from-git

发布当前 commit 中打上 tag version 的包

(3)lerna publish from-packages

发布 package 中 pkg.json 上的 version 在 registry(高于 latest version)不存在的包

下面是lerna publish的执行逻辑图解,以及存在的问题



从上面这个图可以看到其中会有一些坑:

坑1:分支3的情况,因为开发者自己打的一些标签会影响lerna查找变更,可能会造成一些变更的包没有发布

解决办法:
(1)尽量避免自己打Tag
(2)或者只在一个专门的分支上,例如master,专门运行 lerna publish进行发布,这个分支不能自己打其他Tag

坑2:几条分支同时进行的情况,可能生成了相同的版本号,从而发生版本冲突

解决办法:
(1)分支开发者之间约定好各自版本号
(2)或者只在一个专门的分支上,例如master,专门运行lerna publish进行发布

坑3:运行lerna publish如果中途有包发布失败,再运行lerna publish的时候,因为Tag已经打上去了,所以不会再重新发布包到NPM

解决办法:
(1)运行lerna publish from-git,会把当前标签中涉及的NPM包再发布一次,PS:不会再更新package.json,只是执行npm publish
(2)运行lerna publish from-package,会把当前所有本地包中的package.json和远端NPM比对,如果是NPM上不存在的包版本,都执行一次npm publish

lerna版本管理的两种模式

分为固定版本和独立版本,即lerna.json的version字段配置

1、固定版本管理,version为指定版本号,如果想自动将所有包版本绑定在一起时使用此方式。lerna.json的version是最新发布的版本号。

每次publish会检查有修改的包,先修改lerna.json的version,下次发布会在此基础上递增。
注意:

(1)有相互引用的情况下,被引用的的包修改,引用的包的版本号会一同变更

(2)如果主版本为零,并选择任何非预发布版本号,将导致为所有包发布新版本,即使自上次发布以来并非所有包都已更改

2、独立版本管理,version配置为字符 'independent', lerna.json配置如下:

每次publish会检查有修改的包,然后对依次对每个package的version选择更新
注意:

(1)有相互引用的情况下,被引用的的包修改,引用的包也会被列入预发布的列表

五、公共依赖提升lerna bootstrap --hoist 与 lerna + yarn workspace

当你管理的多个工程下面如果很多依赖重复安装,这就很影响效率,lerna提供了依赖提升的功能,lerna bootstrap --hoist。

1、只需要在lerna bootstrap后加上 --hoist, 或者在lerna.json的command配置hoist参数,就可以使用这个功能,但使用时需要注意以下几点:

(1)当不同工程的相同依赖项,不同版本是怎么处理的:lerna会对比版本占比多的依赖项提取到根目录,如果版本都不同,按顺序取最后一个包的版本提升,其他版本在各自工程下安装。

(2)node的模块规范是不断向上找node_modules寻找依赖,但如果你的代码规范不是commonjs的引入方式,可能会找不到依赖,这里需要你自己规范你的引用方式。

(3)如果你在某个工程引用了不属于当前工程的依赖项,但是其他工程有这个依赖项,你一样可以从提升的node_modules里获取到, 并不会报错,但是你可能不知道你的依赖项并没有在package.json中,这里可以使用eslint-plugin-import检查所有新导入是否来自 package.json

2、最优解 lerna + yarn workspace

lerna默认是在npm的基础上做的依赖提升,但现如今大多数工程都是使用yarn来管理, yarn的优势这里不多赘述(了解更多npm和yarn的对比),如果你的包管理方式是yarn,那么就可以使用yarn workspace来代替lerna 的hoist,所以用lerna结合yarn workspace,即为目前多工程管理的最优解。

事实上yarn workspace和lerna bootstrap --hoist做的事情大致是一样的,只不过yarn workspace的实现可以调用yarn的所有能力,相对lerna的实现更底层也更简易,yarn也是受到了lerna的启发才衍生了yarn workspace,

yarn workspace文档

后面lerna也配合yarn提供了yarn workspace的配置,将依赖管理全权交给yarn,

lerna配合yarn workspace的PR(大佬的code review值得学习😄)

这里看完PR就很清楚了,其实就是:

(1)lerna在lerna.json里增加了useWorkspaces参数
(2)useWorkspaces为true时,执行lerna bootstrap会检查你的根package.json是否配置了workspace和private,未配置会报错提示,否则就相当于执行了yarn,将依赖管理和软连接的建立完全交给yarn。

具体使用就是在根目录的package.json下添加:

在lerna.json里配置:

这样就可以达到依赖管理全部用yarn,发布版本和测试部署用lerna,实际上你可以直接使用yarn worksapce而不用lerna bootstrap,但是bootstrap后面也还是做了一些事情的,所以看个人需要。

六、lerna的一些常用命令

1、lerna bootstrap

初始化项目依赖以及建立link关系以及预发布处理

2、lerna publish

lerna publish做了一套npm标准的发布流程管理

3、lerna changed

用来查看发生改变的package,即预发布的包

4、lerna clean

用来清空所有package的node_moudles依赖

5、lerna run

用来执行每个package下的scripts命令

6、lerna add

用来给package添加依赖,可以全部添加,也可以指定添加

有兴趣了解更多命令在lerna github

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值