Skip to main content

lerna

· 10 min read

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第 2 天,点击查看活动详情

一、背景​

或许在开发多包的过程中,总会遇到多包的发布工作流问题,详细解释就是一个 npm 包,由多个 npm 相互依赖构成,发布 npm 包 1,对其有依赖的 npm 包 2 也要一同发布,那么怎么才能将这个发布工作流简单化呢?

实现在发布 npm 包 1 时,自动检测依赖 npm 包的其他包,并同时发布,更新版本。

答案大家都知晓,那便是使用多包管理工具 lerna。

但是 lerna 官方文档(lerna 中文文档)不齐全,学习成本甚高,本文欲打造一个最详细的 lerna 手册,帮助查阅指令,熟悉 lerna。

二、lerna 介绍​

lerna 是一个优化使用 git 和 npm 管理多包存储库工作流的工具。

它具有以下功能:

  • 自动解决 packages 之间的依赖关系;
  • 通过 git 检测文件改动,自动发布;
  • 根据 git 提交记录,自动生成 CHANGELOG。

三、工作模式​

lerna 支持 2 种工作模式,分别是默认模式-Locked mode和Independent mode。

默认模式-Locked mode​

每次发布,所有有改动的包自动更新版本号,所有包的版本一致,版本号维护在 lerna.json 的 version 中。

Independent mode​

每次发布时,将提示每个已更改的包,以及其建议的版本号,每个 package 都有自己的版本号。

设置方式:

lerna init --independent

或修改 lerna.json:

version: "independent"

四、常用指令​

1. lerna init​

初始化一个 lerna 工程或者升级现有 lerna 项目到当前版本的 lerna。

lerna init

执行成功后,目录下将会生成这样的目录结构。

 - packages(目录)
- lerna.json(配置文件)
- package.json(工程描述文件)

2. lerna create​

创建一个 package,指定包名,可指定包位置。

lerna create < name > [location]

lerna create package1
lerna create package1.1 packages/package1

3. lerna add​

为包添加依赖。

  • --dev devDependencies 替代 dependencies
  • --exact 安装准确版本,就是安装的包版本前面不带^, Eg: "^2.20.0" ➜ "2.20.0"
lerna add lodash packages/module-1

4. lerna bootstrap​

将本地包链接在一起并安装其余的包依赖项。

lerna bootstrap

5. lerna list​

列出所有的包。

lerna list

6. lerna import​

导入本地已经存在的包。

lerna import [npm 包所在路径]

项目包建立软链,类似 npm link。

lerna link

8. lerna clean​

删除所有包的 node_modules 目录。

lerna clean

9. lerna changed​

列出自上次更改后已更改的本地包。

lerna changed

10. lerna publish​

发布包。

lerna publish

11. lerna diff​

区分自上次发布以来的所有包或单个包

lerna diff

12. lerna info​

打印有关本地环境的调试信息。

lerna info

13. lerna run​

在包含该脚本的每个包中运行 npm 脚本。

lerna run dev

在包含该脚本的指定包中运行 npm 脚本。

lerna run dev --scope=packageA

14. lerna version​

更新版本。

lerna version

五、lerna + yarn workspaces 实践​

1. 安装​

npm install lerna -g

2. 创建项目​

mkdir lerna-demo

3. 初始化项目​

cd ./lerna-demo
lerna init

其中 package.json & lerna.json 如下:

// package.json
{
"name": "root",
"private": true, // 私有的,不会被发布,是管理整个项目,与要发布到npm的解耦
"devDependencies": {
"lerna": "^4.0.0"
}
}

// lerna.json
{
"packages": [
"packages/*"
],
"version": "0.0.0"
}

4. 启用 yarn workspaces​

各个库之间存在依赖,如 A 依赖于 B,因此我们通常需要将 B link 到 A 的 node_module 里,一旦仓库很多的话,手动的管理这些 link 操作负担很大,因此需要自动化的 link 操作,按照拓扑排序将各个依赖进行 link。

启用 yarn workspaces 可以把所有的依赖提升到顶层的 node_modules 中,并且在 node_modules 中链接到本地的 package,自动的帮忙解决安装和 link 问题。

修改 package.json:

{
"private": true, // 只有私有项目可以开启
"workspaces": ["packages/*"]
}

修改 lerna.json:

{
"useWorkspaces": true,
"npmClient": "yarn"
}

5. 添加 package​

lerna create packageA
lerna create packageB

6. 添加、删除、清除包依赖​

yarn workspaces 添加依赖:

# 将packageA作为packageB的依赖进行安装:
$ yarn workspace packageB add packageA
# 给所有的package安装依赖:
$ yarn workspaces add lodash
# 给root 安装依赖:
$ yarn add -W -D typescript

yarn workspaces 删除依赖:

# 删除packageB的依赖packageA:
$ yarn workspace packageB remove packageA
# 给所有的packages删除依赖:
$ yarn workspaces remove lodash
# 给root 删除依赖:
$ yarn remove -W -D typescript

yarn workspaces 安装全部依赖:

yarn install

yarn install 等价于 lerna bootstrap --npm-client yarn --use-workspaces,把所有的依赖提升到顶层的 node_modules 中,并且在 node_modules 中链接到本地的 package,自动的帮忙解决安装和 link 问题。

yarn workspaces 清除 node_modules:

yarn workspaces run clean

7. 项目构建​

构建所有包:

区别于普通项目之处在于各个 package 之间存在相互依赖,如 packageB 只有在 packageA 构建完之后才能进行构建,否则就会出错,这实际上要求我们以一种拓扑排序的规则进行构建。

lerna 支持按照拓扑排序规则执行命令, --sort 参数可以控制以拓扑排序规则执行命令。

# 以拓扑排序规则在包含该脚本的每个包中运行 npm run dev 脚本。
lerna run dev --stream --sort
# 以拓扑排序规则在包含该脚本的每个包中运行 npm run build 脚本。
lerna run build --stream --sort

构建指定包:

# 在 packageA 包中运行 npm run dev 脚本。
lerna run dev --stream --scope=packageA
# 在 packageA 包中运行 npm run build 脚本。
lerna run build --stream --scope=packageA

8. 发布​

lerna publish

发布指令 lerna publish 内置以下步骤:

  • 条件验证:包含验证测试是否通过,是否存在未提交的代码,是否在主分支上进行版本发布操作等等条件验证;

  • version_bump:发版的时候需要更新版本号,这时候如何更新版本号就是个问题,一般大家都会遵循  semVer 语义;

  • 生成 changelog:为了方便查看每个 package 每个版本解决了哪些功能,我们需要给每个 package 都生成一份 changelog 方便用户查看各个版本的功能变化;

  • 生成 git tag:为了方便后续回滚问题及问题排查通常需要给每个版本创建一个 git tag;

  • git 发布版本:每次发版我们都需要单独生成一个 commit 记录来标记 milestone;

  • 发布 npm 包:发布完 git 后我们还需要将更新的版本发布到 npm 上,以便外部用户使用。

小结​

本文从 5 个方面介绍了 lerna:

  • 背景
  • 介绍
  • 工作模式
  • 常用指令
  • lerna + yarn workspaces 实践

相信你已经很熟悉 lerna 的使用了,下方还列举了参考资料,可以自行扩展阅读。

希望能对你有所帮助,感谢阅读~

别忘了点个赞鼓励一下我哦,笔芯 ❤️

参考资料​