初始化
创建空文件夹,然后运行:
1 | npx lerna init |
这行命令会创建一个空的packages
文件夹,一个package.json
和 lerna.json
1 | |-- mono-repo |
package.json
有一点需要注意,他的private
必须设置为true
,因为本身并不是一个项目,而是承载多个子项目的项目,所以他自己不能直接发布,发布的应该是 packages/下面的各个子项目。
1 | "private": true |
lerna.json 初始化长这样:
1 | { |
packages
字段就是标记你子项目的位置,默认就是packages/
文件夹,他是一个数组,所以是支持多个不同位置的。
另外一个需要特别注意的是version
字段,这个字段有两个类型的值,一个是像上面的0.0.0
这样一个具体版本号,还可以是independent
这个关键字。如果是具体版本号,那lerna
管理的所有子项目都会有相同的版本号,如果你设置为independent
,那各个子项目可以有自己的版本号。
因为我们的组件都是需要独立版本号,所以直接将version
设置为independent
1 | { |
创建子项目
创建子项目可以使用 lerna 的命令来创建:
1 | lerna create <name> |
通过 create 创建的子项目目录:
1 | |-- mono-repo |
这个是使用lerna create
默认生成的目录结构,__test__
文件夹下面放得是单元测试内容,lib
下面放得是代码。实际使用过程中可以进行调整。
安装依赖项
lerna bootstrap
packages/
下面的每个子项目有自己的依赖包,可使用命令:
1 | lerna bootstrap |
删除已经安装的子项目node_modules
可以手动删除,也可以使用:
1 | lerna clean |
具体命令含义可参考
yarn workspace
lerna bootstrap --hoist
虽然可以将子项目的依赖提升到顶层,但是他的方式比较粗暴:先在每个子项目运行npm install
,等所有依赖都安装好后,将他们移动到顶层的node_modules
。这会导致一个问题,如果多个子项目依赖同一个第三方库,但是需求的版本不同怎么办?比如我们三个子项目都依赖 antd,但是他们的版本不完全一样:
1 | // @mono-repo/project_1 |
这时候就需要介绍yarn workspace
了,他可以解决前面说的版本不一致的问题,lerna bootstrap --hoist
会把所有子项目用的最多的版本移动到顶层, 从而导致某些子项目依赖不正确,而yarn workspace
则会检查每个子项目里面依赖及其版本,如果版本不一样则会留在子项目自己的node_modules
里面,只有完全一样的依赖才会提升到顶层。
还是以上面这个antd
为例,使用yarn workspace
的话,会把project1
和project2
的 3.1.0 版本移动到顶层,而project3
项目下会保留自己 4.9.4 的 antd,这样每个子项目都可以拿到自己需要的依赖了。
yarn workspace
使用也很简单,yarn 1.0
以上的版本默认就是开启workspace
的,所以我们只需要在顶层的package.json
加一个配置就行:
1 | // 顶层package.json |
在 lerna.json 里面指定npmClient
为yarn
,并将useWorkspaces
设置为true
,稍稍改动变成这样:
1 | { |
使用了yarn workspace
,我们就不用lerna bootstrap
来安装依赖了,而是像以前一样yarn install
就行了,他会自动帮我们提升依赖,这里的yarn install
无论在顶层运行还是在任意一个子项目运行效果都是一样的。
更多请参考
启动子项目
我们可以到子项目的目录运行 start 命令, 但是频繁切换文件是在太麻烦,lerna 提供了相应的命令以帮助我们直接在顶层运行:
1 | lerna run [script] |
比如我们在顶层运行了 lerna run start,这相当于去每个子项目下面都去执行 yarn run start 或者 npm run start,具体是 yarn 还是 npm,取决于你在 lerna.json 里面的这个设置:
1 | "npmClient": "yarn" |
如果我只想在其中一个子项目运行命令,应该怎么办呢?加上--scope
就行了,比如我就在顶层的package.json
里面加了这么一行命令:
1 | // 顶层package.json |
注意scope
后面的项目名称不是目录名,而是子项目package.json
的name
1 | // 子项目project_1的package.json |
引入公共组件
当我们的@mono-repo/project_2
要引用@mono-repo/project_1
的组件,我们需要先在@mono-repo/project_2
的package.json
里面将依赖加上,我们可以去手动修改他,也可以使用lerna
命令:
1 | lerna add @mono-repo/project_1 --scope @mono-repo/project_2 |
这样我们可以在project2
中引入project1
的组件,但是需要注意多个项目引用时,要避免各个子项目之间的循环引用。
组件库相关请参考组件库构建与编写
发布
发布直接使用 lerna publish,因为此前我们已经将 version 修改为 independent,所以在发布时,只会自动更新有变动的子项目以及依赖该子项目的子项目的版本号。
更多发布命令参数及解释请参考lerna/publish