一、介绍

在学习wangEditor的过程中,了解到Lerna,这里记录下学习与使用过程。

基本概念就不再赘述了,直接参考这里。在学习过程中也查阅了部分博文,发现有些朋友不是很清楚这个东西是解决什么问题的,这里举例说明下。

在一个成熟的开发团队中,往往比较注重代码的积累、复用、共享,单就前端来说,一般会积累如下几个开发包:frame、components、charts、utils等等

  • frame:路由复用策略、路由守卫、HTTP拦截器、国际化、主题。。。
  • components、charts:和开源的基础组件库、图表库不同,可能是包含一些它们没有的组件、图表,也可能是一些包含通用业务的组件、图表
  • utils:uuid、deepMerge。。。

这些开发包如果是独立的,也不是不可以,只是管理、使用起来比较麻烦,如果相互之前再有依赖关系的话,那就不是比较麻烦了,而是相当麻烦。那么Lerna就是为了解决这个问题的。同时它还能够根据Git提交记录,自动生成版本号、ChangeLog,省去了繁琐的配置步骤,何乐不为呢?

二、基本使用

参考这里的入门,很容易初始化一个Lerna工程。
接下来就是创建子包了,可以直接手动创建,比如:

1
2
3
4
5
6
7
# 在packages下创建文件夹sub-package
$ cd packages
$ mkdir sub-package

# 进入文件夹初始包
$ cd sub-package
$ yarn init

或者采用lerna指令创建文件夹并初始化,比如:

1
$ lerna create sub-package

在我看来,一般我们不会从零初始化一个Lerna工程,现在3大前端框架、webpack、vite等都提供了脚手架,直接一个命令就可以初始化一个前端工程,对应的tsconfig.json、package.json、README.md、angular.json、vue.config.js等都有了,如果要是从一个空的Lerna工程手动新建这些,着实费劲。
所以这里就不过多介绍创建子包之后的操作了,直接进入下一环节。

三、在Angular工程中使用Lerna@7

我们都知道,Angular是提供在一个工程中创建多个Library的功能的,只不过这些Library的发包仍然是独立的,版本号、ChangeLog也是需要手动维护的,并不友好。
那么在现有的Angular工程中如何使用Lerna呢?具体步骤如下:

1、初始化Angular工程

1
$ ng new my-test

2、新建Library

1
2
3
$ cd my-test
$ ng g lib my-lib1
$ ng g lib my-lib2

3、初始化Lerna

1
$ lerna init --packages="projects/*"  // Angular管理子包的目录名默认为projects

此时会在my-test目录下多出一个lerna.json文件。

4、调整Library配置

Angular默认是将Library打包到工程根目录下的dist目录的,这里做个调整,打包到各自的dist目录:

1
2
3
4
5
6
7
8
// ng-package.json
{
"$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
"dest": "./dist", // 这里
"lib": {
"entryFile": "src/public-api.ts"
}
}

在各自的package.json中添加如下内容(具体package.json详解请参考这里):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
{
...
"repository": {
"type": "git",
"url": "git+https://gitee.com/xxxx/my-test.git"
},
// 如果不配置,默认就是https://www.npmjs.com/
"publishConfig": {
"access": "public",
"registry": "http://npm:npm@ip:port/nexus/content/repositories/npm-repo/"
},
// Lerna默认会将package.json所在目录的所有子内容都发布出去,这里配置只发布dist目录下的内容
"files": [
"dist"
],
// 下面的视情况而定
"main": "dist/bundles/my-lib1.umd.js",
"module": "dist/fesm2015/my-lib1.js",
"es2015": "dist/fesm2015/my-lib1.js",
"esm2015": "dist/esm2015/my-lib1.js",
"fesm2015": "dist/fesm2015/my-lib1.js",
"typings": "dist/my-lib1.d.ts"
}

5、自动生成版本号和ChangeLog

正常开发完代码并git commit之后,

1
$ lerna version --conventional-commits

这将会根据Git commit规范生成版本号和ChangeLog,同时会生成Tag并一起推送到远程Git仓。

6、发布

1
$ lerna publish from-git --yes

2024-10-29更新
关于步骤5、6的特殊说明:

  • 虽然全局安装了lerna,但也不能直接在终端执行上述命令,会报如下错误:
    lerna ERR! EUNCOMMIT Working tree has uncommitted changes, please commit or remove the following changes before continuing:
    原因是lerna会更新package.json中的版本号和CHANGELOG.md文件,但是坑爹啊有木有,明明是你的机制改动了我本地文件,又说我本地有残留文件,搞不懂为什么会这样
  • 需要将上述命令放到package.json的scripts中,如下:
    “scripts”: {
    “version”: “lerna version –conventional-commits”,
    “publish”: “lerna publish from-git –yes”,
    },
  • 然后通过npm run versionnpm run publish执行,就不会报错了

7、安装依赖

如果只想给某个子包安装依赖 或者 子包之间有依赖关系,可通过如下命令实现:

1
2
3
$ npm install <dependency> -w <package>
// dependency可以是子包名称,也可以是开源依赖
// package为目标子包名称,是子包的package.json中的name值

2024-08-11更新
关于步骤7的特殊说明:
Lerna@8版本,已经不需要像步骤7那样执行命令了,正常使用npm install\uninstall即可,当安装的是自己的子包时,也无需添加任何额外的参数,Lerna会自动帮我们处理,并且在node_modules目录下,子包的目录会通过软链接的形式指向实际的代码目录,就像这样
软链接.png

更多细节可参考这里