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 modeIndependent 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 的使用了,下方还列举了参考资料,可以自行扩展阅读。

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

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

参考资料