Lerna是一个使用git和npm来处理多包依赖管理的工具,利用它能够自动帮助我们管理各种模块包之间的版本依赖关系。可以让你在主项目下管理多个子项目,从而解决了多个包互相依赖,且发布时需要手动维护多个包的问题。它属于monorepo
类型,当你的项目有相关联时最好使用monorepo
方式进行管理。
我们一般会把一个大型项目才分两大部分:业务模块 通用模块。 由于通用模块会被多个业务模块使用,往往是通过NPM包提供服务。Lerna很好的管理多个包以及他们的依赖关系。
1.工作模式:
Lerna允许我们使用两种模式来管理我们的模块:Fixed 模式和Independent模式。
- Fixed/Locked 模式 (默认)
通过在lerna.json
中指定version
,当你运行lerna publish
时,如果其中某一个包至上次发布以来有更新,则将会更新version
。
这个模式是babel目前使用的模式,当你想把所有包关联在一起的时候可以考虑使用这种模式,需要注意的是,当其中某个包升级了大版本之后,其他的每个包都会自动升级大版本。
- Independent mode
lerna init --independent
独立模式允许您更具体地更新每个包的版本,并对一组组件有意义。跟semantic-release等工具配合使用会更好。
2.核心原理:
monorepo 和 multrepo 区别:
monorepo: 是将所有的模块统一的放在一个主干分支之中管理。
multrepo: 将项目分化成为多个模块,并针对每一个模块单独的开辟一个分支来进行管理。
3.文件软链:
Lerna实现内部模块的软链和管理,是使用了symlink-dependencies包。最终使用fs.symlink函数实现了文件软链。代码: https://github.com/lerna/lerna/blob/master/utils/create-symlink/create-symlink.js#L20
4.应用场景:
- 中大型项目,不过分庞大的项目,整合到一起有100G源码的话,不建议用。
- 多模块/插件化项目,把官方维护的插件都作为package非常合适。
- 有强大的构建工具,能满足所有模块的build需求。
- 需要持续集成机制(例如React – CircleCI)确认修改带来的影响,另一方面还需要不同团队之间互相信任,否则会经常出现一个团队的变更影响了另一个团队的情况,需要回滚掉别人的修改,反而影响效率。
5.初始化项目:
首先,先建一个新项目,接着我们全局安装lerna,并执行初始化操作,再上传到git仓库上:
代码语言:javascript复制npm intall lerna -g
mkdir lerna-demo && cd $_
lerna init
git init
git add .
git commit -m "Initial Commit"
git remote add origin http://github.com/scq000/lerna-demo.git
git push -u origin master
ls
执行完上述命令后,就会在当前目录下生成以下几个文件:
packages/ package.json lerna.json
其中: packages目录用来存放我们需要拆分的各种公共代码库。lerna.json文件里面记录了lerna的相关配置信息:
代码语言:javascript复制{
"version": "1.1.3",
"npmClient": "npm",
"command": {
"publish": {
"ignoreChanges": ["ignored-file", "*.md"],
"message": "chore(release): publish"
},
"bootstrap": {
"ignore": "component-*",
"npmClientArgs": ["--no-package-lock"]
}
},
"packages": ["packages/*"]
}
分别介绍每个配置项的功能:
- version: 记录当前项目的版本号
- npmClient: 你可以指定使用npm, cnpm或yarn来执行命令
- command.publish.ignoreChanges: 忽略特定的项
- command.publish.npmClientArgs: 当执行lerna bootstrap命令时,传给npm install的参数
- command.publish.message: 发布模块的时候,填写的commit信息
- packages: 模块包默认所在的地址
你可以根据需要自己更改相应的配置。
6.新建模块
为了演示方便,我们新建两个模块, moduleA和moduleB, 并让moduleA依赖moduleB:
代码语言:javascript复制lerna create module-a
lerna create module-b
# 将本地包链接起来,可以直接引用
lerna link
修改module-b 的入口文件:
代码语言:javascript复制export const sayHello() {
return "hello world";
};
修改module-a 的入口文件:
代码语言:javascript复制const moduleB = require('module-b');
const moduleA = function() {
console.log(moduleB.sayHello());
}
export default moduleA;
git示例: https://github.com/Dark-YiFeng/Lerna
7.发布
完成修改后,我们可以直接发布新的模块
代码语言:javascript复制lerna publish
然后,根据提示输入版本号等,lerna就会自动帮我们给包加上tag,并上传到对应的仓库中去。
8.Lerna指令
安装依赖
代码语言:javascript复制lerna bootstrap
查看本地包列表
代码语言:javascript复制lerna list
删除安装依赖
代码语言:javascript复制lerna clean
建立软链
代码语言:javascript复制lerna link
发布安装包
代码语言:javascript复制lerna publish
创建一次lerna工作流
从lerna boostrap(依赖包安装) --> 开发模块 --> git commit --> lerna changed(查看包变化) --> lerna publish。
lerna bootstrap // 安装依赖包 lerna list // 本地依赖包 lerna changed // 待发布包列表 lerna publish // 发布
9.Lerna高阶操作(黑科技)
publish 高级应用: 某些发布的情况,开发者需要指定安装包版本,或者指定子目录发布。
代码语言:javascript复制lerna publish --dist-tag next // 指定当前版本号
lerna publish --contents dist // 指定dist目录为发布目录
bootstrap 性能提升: 如果安装包里面有多个基础依赖包,可以使用 --hoist 把NPM包安装到根目录,提升性能。
lerna bootstrap --hoist // 提升到根目录