概要
lerna是GitHub上面开源的一款js代码库管理软件, 用来对一系列相互耦合比较大、又相互独立的js git库进行管理。解决各个库之间修改混乱、难以跟踪的问题。
Lerna 是一个工具,它优化了使用 git 和 npm 管理多包存储库的工作流。对于一些功能比较全的库,我们往往会把各个小功能拆分成独立的npm库,他们直接有比较强的依赖关系。比如:Babel、React等开源代码都是按照这种方式进行处理的。
- 假设主项目是 vuejs,依赖两个自研 npm 包,这两个包也依赖 vuejs,现在主项目要升级 vue 版本,那么这两个 npm 包也得跟着升级,且需要升级两次(一个包一次),提升效率是否只发一次呢。
- 假设有两个 npm 包A和B,A依赖B,那么每当B有更新时,要想让A用上B的更新,需要B发版,然后A升级B的依赖,可否能同时发布升级节省效率
优势
- lerna,一种多包依赖解决方案,简单来讲:
1.可以管理公共依赖和单独依赖;
2.多package相互依赖直接内部 link,不必发版;
3.可以单独发布和全体发布;
4.将一个大的 package 分割成一些小的 packcage 便于分享,调试;多包放一个git仓库,也有利于代码管理,如配置统一的代码规范
5.类似框架还有Yarn workspace;
两种工作模式
Fixed/Locked mode (default)
vue,babel 都是用这种,在 publish 的时候,所有的包版本都会更新,并且包的版本都是一致的,版本号维护在 lerna.jon 的 version 中;
Independent mode
lerna init --independent
独立模式,每个 package 都可以有自己的版本号。版本号维护在各自 package.json 的 version 中。每次发布前都会提示已经更改的包,以及建议的版本号或者自定义版本号。这种方式相对第一种来说,更灵活。
全局安装并init
yarn global add lerna
or
npm install -g lerna
lerna init --independent
初始化项目时使用 Independent 模式
Independent 模式可以单独发版,更灵活
成功后,生成目录:
- packages(目录)
- lerna.json(配置文件)
- package.json(工程描述文件)
添加子package
cd packages && mkdir moduleA && cd moduleA && touch index.js && npm init
假如touch创建文件报错
npm install touch-cli -g 解决
--access 当使用scope package时(@qinzhiwei/lerna),需要设置此选项 [可选值: “public”, “restricted”][默认值: public]
--bin 创建可执行文件 --bin <executableName>
--description 描述 [字符串]
--dependencies 依赖,用逗号分隔 [数组]
--es-module 初始化一个转化的Es Module [布尔]
--homepage 源码地址 [字符串]
--keywords 关键字数 [数组]
--license 协议 [字符串][默认值: isc]
--private 是否私有仓库 [布尔]
--registry 源 [字符串]
--tag 发布的标签 [字符串]
-y, --yes 跳过所有的提示,使用默认配置 [布尔]
扩展:
ISC许可
- ISC许可证是一种开放源代码许可证,在功能上与两句版的BSD许可证相同。
- 这份许可证是由ISC(Internet Systems Consortium)所发明,在ISC释出软件时所使用的。
- 当前版本 ISC License (ISC)
MIT许可
- MIT许可证之名源自麻省理工学院(Massachusetts Institute of Technology, MIT),又称“X条款”(X License)或“X11条款”(X11 License)。
- MIT是和BSD一样宽范的许可协议,作者只想保留版权,而无任何其他了限制。也就是说,你必须在你的发行版里包含原许可协议的声明,无论你是以二进制发布的还是以源代码发布的。
- 当前版本 The MIT License
常用命令
lerna create
lerna create <name> [loc]
创建一个包,name包名,loc 位置可选,例如:
# 根目录的package.json
"workspaces": [
"packages/*",
"packages/@utils/*"
],
# 创建一个包gpnote默认放在 workspaces[0]所指位置
lerna create dateUtils
# 创建一个包gpnote指定放在 packages/@utils文件夹下,注意必须在workspaces先写入packages/@utils,看上面
lerna create dateUtils packages/@utils
命名通常用例如@gds/plugin-XXXX
bootstrap
使用bootstrap命令,会下载所有定义在package.json中的依赖包。相当于执行npm install
,并且链接所有依赖包。
publish(重点)
当你完成某个包的更新后,就可以使用lerna publish
命令来发布新版本的包。执行这条命令的时候,你可以指定版本号,然后lerna就会自动给你加更新版本号,加tag并提交到git仓库上去。(ps:过程中遇到很坑的问题,本地代码push远程后,执行publish指令,会基于当前lerna.json中的版本号让你选默认升级版本号,然后会覆盖本地文件版本号,报错:
lerna ERR! EUNCOMMIT Working tree has uncommitted changes,
please commit or remove the following changes before continuing:
)
(坑爹啊有木有)明明是你的机制改动了我本地文件,又说我本地有残留文件;最后查了很多资料,最好方式是以下第三种上传方式来解决。
官方文档中,lerna publish 一共有这样几种执行表现形式:
1.lerna publish 永远不会发布 package.json 中 private 设置为 true 的包
发布自上次发布来有更新的包(这里的上次发布也是基于上次执行lerna publish 而言)
2.发布在当前 commit 上打上了 annotated tag 的包(即 lerna publish from-git)
3.(重要重要重要)发布在最近 commit 中修改了 package.json 中的 version (且该 version 在 registry 中没有发布过)的包(即 lerna publish from-package)
发布在上一次提交中更新了的 unversioned 的测试版本的包(以及依赖了的包)
lerna publish 本身提供了不少的 options,例如支持发布测试版本的包即 (lerna version --canary)。
add
假设你想往你的开发项目中特定包中加入依赖,你就可以使用add
命令轻松实现:
# 给a, b 包中加入Lodash,会同时改变a,b模块中packages.json文件
lerna add lodash packages/a packages/b
# 给a 包中加入jquery, 使用--dev参数是使依赖加入到devDependencies中
lerna add jquery packages/a --dev
# 你也可以使用通配符, 下面这命令,会往所有re开头的模块包中加入依赖
lerna add jquery packages/re-*
# 指定特定的范围,要使用--scope参数,如下:给b包安装a模块
lerna add a --scope=b
clean
执行clean命令,用来删除所有模块下node_modules中的npm包。
import
你可以使用import命令导入已有的模块,并且会保留所有的git commit记录。
list
列出项目中所有的模块。
run
在每个包含该脚本的模块中运行npm脚本。