多包管理工具Lerna

424 阅读5分钟

多包管理工具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 clientlerna 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冲突, 用户可以使用这个选项所谓单独的commitlerna 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.23.x的lerna指定cnpm源publish均无效。