多包管理工具Lerna
Lerna是一个工具,它优化了使用git和npm管理多包存储库的工作流。
背景
1、将一个大的 package 分割成一些小的 packcage 便于分享,调试
2、在多个 git 仓库中更改容易变得混乱且难以跟踪
3、在多个 git 仓库中维护测试繁琐
Lerna优点
1、可以管理公共依赖和单独依赖;
2、多package相互依赖直接内部 link,不必发版;
3、可以单独发布和全体发布
4、多包放一个git仓库,也有利于代码管理,如配置统一的代码规范
Lerna两种工作模式
Fixed/Locked mode (default)
固定模式,当使用lerna init命令初始化项目时,就默认为固定模式。
固定模式中,packages下的所有包共用一个版本号(version),会自动将所有的包绑定到一个版本号上
(该版本号也就是lerna.json中的version字段),所以任意一个包发生了更新,这个共用的版本号就会
发生改变。
Independent mode
独立模式,每个 package 都可以有自己的版本号。版本号维护在各自 package.json 的 version
中。每次发布前都会提示已经更改的包,以及建议的版本号或者自定义版本号。这种方式相对第一种来说,
更灵活
Lerna实战
下面以独立模式为例进行演示
初始化
npm i -g lerna (需要指定npm源:registry=http://ires.58corp.com/repository/58npm/)
mkdir lerna && cd lerna
lerna init --independent (--independent 独立模式设置)
生成目录
- lerna
- packages(目录)
- lerna.json(配置文件)
- package.json(工程描述文件)
添加子package
cd packages && mkdir moduleA && cd moduleA && touch index.js && npm init
手动创建
lerna create <name> [loc]
创建一个包,name包名,loc 位置可选
添加依赖
公共依赖
lerna add lodash
单独依赖
lerna add base --scope=package-1 (base为添加的包名,scope=要添加的项目名)
## yarn Workspaces(工作区)
lerna安装源默认是 npm, 每个子package都有自己的node_modules,每个子package安装包都在该项目package.json中管理
设置yarn Workspaces(工作区)后,只有顶层有一个node_modules,所有公共安装包都在顶层(lerna.json同层)的package.json中进行管理
启用 yarn Workspaces 方式
# 顶层package.json 文件加入
"private": true,
"workspaces": [
"packages/*"
],
# 顶层lerna.json 文件加入
"useWorkspaces": true,
"npmClient": "yarn",
Lerna常用api
lerna publish
lerna publish做哪些事情
- 运行lerna updated来决定哪一个包需要被publish
- 如果有必要,将会更新lerna.json中的version
- 将所有更新过的的包中的package.json的version字段更新
- 将所有更新过的包中的依赖更新
- 为新版本创建一个git commit或tag
- 将包publish到npm上
(私有包不会被发布,需要在该包package.json文件里写明private:true)
当然首先你要登陆自己的npm账号
然后就会提醒我们进行当前的版本选择,是升级一个小版本还是一个大版本
虽然就会进行统一的处理,发布到npm上去,并且统一所有包的版本,并且会将代码进行提交
最后我们就可以在npm上搜索到我们的包了
也可以进行下载了
lerna bootstrap 安装依赖
如果 packages 下的包有相互依赖,我试了一下直接lerna bootstrap,已经帮我们进行了 lerna link 了,而 lerna link 只是帮我们做软链接工作。
而且即使发布到线上,执行 `lerna bootstrap` ,也是会 link 本地依赖包,而不是去线上安装。
| lerna bootstrap参数 | 作用 | 命令 |
|---|---|---|
| –hoist | 把依赖安装到根目录的node_modules | |
| –ignore | 忽略的包 | –ignore test-* 忽略名称以test开头的包 |
| –scope | 指定的包 | 参数的含义是指包的名称 |
| –registry | 指定registry | |
| –npm-client | 指定安装用的npm client | lerna bootstrap --npm-client=yarn |
| –use-workspace | 使用yarn workspace |
lerna list
列举当前lerna库包含的包
| lerna list参数 | 作用 |
|---|---|
| –json | 显示为json格式 |
| –all | 显示包含private的包 |
| –long | 显示更多的扩展信息 |
lerna import
导入指定git仓库的包作为lerna管理的包
eg: lerna import ../Starbucks
| lerna import参数 | 作用 | 命令 |
|---|---|---|
| –flatten | 如果有merge冲突, 用户可以使用这个选项所谓单独的commit | lerna import ~/Product --flatten |
| –dest | 可以指定导入的目录(lerna.json中设定的目录) | lerna import ~/Product --dest=utilities |
lerna run
运行npm命令
eg: lerna run --scope my-component test (--scope my-component 指定运行那个子package的npm命令)(test package.json中声明的命令)
lerna link
项目包建立软链,类似npm link(lerna add 和lerna bootstrap时都会实现link的功能)
lerna link会将所有package.json中申明引入的本地依赖进行安装,非本地的不会
lerna clean
删除所有包的node_modules目录
lerna exec
运行shell命令
eg: lerna exec --scope=hou-base npm uninstall hou-test-base-one
卸载指定项目下的指定包
| lerna exec参数 | 作用 | 命令 |
|---|---|---|
| – | 对所以子package执行 | lerna exec – rm -rf ./node_modules |
| –concurrency | 使用给定的数量进行并发执行(输出经过管道过滤,具有不确定性) | lerna exec --concurrency 1 – ls -la |
lerna changed
lerna updated
列出下次发版lerna publish 要更新的包。
支持lerna list的所有参数
原理:
需要先git add,git commit 提交。
然后内部会运行git diff --name-only v版本号 ,搜集改动的包,就是下次要发布的。、
lerna diff
查看自上次发布(打 tag)以来某个 package 或者所有 package 的变化
$ lerna diff
# diff a specific package
$ lerna diff package-name
lerna version
生成新的唯一版本号(使用前需要有commit提交)
| lerna version参数 | 作用 |
|---|---|
| –force-publish | 强制更新版本(跳过lerna changed检查) |
| –no-private | 排除私有包 |
| –ignore-changes | 变更检测时忽略的文件(lerna version --ignore-changes ‘ /*.md’ ‘ /tests/**’) |
| –amend | 减少commit的次数,将当前变更内容随着本次版本变化一次commit |
可能遇到的问题
1、如果我们的package中有webpack,那么其中的loader很有可能会出问题。主要是路径问题,webpack也给出了解决办法,配置webpack 的 resolve.symlinks 就解决这个问题
2、指定cnpm源无效
据gitlab issue publish时不接受参数,只能使用npm仓库。
但是旧版本 2.x 的支持,本人测试,截止到3.3.2,3.x的lerna指定cnpm源publish均无效。