PS:lerna现已不保护了,声明在这里:github.com/lerna/lerna…
能够改用nx
运用lerna构建monorepo
monorepo是什么?
monorepo便是在一个git repository里边办理多个packages或许项目
在实践开发运用中,在哪些场景下可能你会想要运用这种代码办理的方法呢?
- 你们团队是一个以全栈开发为方针的团队,能够将前后端的项目放在一个repository里边进行办理
- 假如你是想运用微服务的,无论是后端微服务仍是前端微服务(Single-SPA)之类的,你就能够在一个repository里边办理多个相关的项目。
- 开源项目中对项目模块分隔办理和发布,例如create-react-app
Lerna
monorepo是一种代码办理的概念,有许多工具都能够帮助你去实现,这里介绍的是Lerna
那么Lerna是什么呢?
官方解释是:
Lerna is a tool that optimizes the workflow around managing multi-package repositories with git and npm.
Lerna在供给了一些对多个package进行操作的指令之外,还供给了一些和对项目发布作业流程的一些支持。
咱们这里运用的lerna v3。
初始化项目
要从一个新项目开端仍是从已有项目出发,都能够运用lerna去创立monorepo的开发模式
lerna供给了两种方法去办理项目,一种是Fixed/Locked mode (default),另一种是Independent mode
差异便是,Fixed/Locked mode的版别操控是整一个repository作为一个整体的,而Independent mode则每个package的版别操控是独立的
咱们这里介绍的是Independent mode的方式
履行下面指令对lerna进行初始化
npx lerna init --independent
会生成一个lerna.json
的文件,这便是lerna的装备文件,内容如下
{
"packages": [
"packages/*"
],
"version": "independent"
}
这里有两个装备,一个是packages,能够用来指定你需求办理的package的目录,默认装备是packages下面的第一级目录下的项目文件夹
假如要嵌套多层,能够改成
{
"packages": [
"packages/**"
]
}
假如需求添加其他目录,例如前后端一起的monorepo,能够修正为
{
"packages": [
"servers/*", "frontend/*"
]
}
详细的目录结构就视详细而定。
假如你是习气运用yarn进行包办理的,咱们还能够界说咱们需求的包办理工具为yarn
{
"version": "1.1.3",
"npmClient": "npm",
"packages": ["packages/*"]
}
详细的详细的lerna.json
装备能够看lerna github上的Readme文档
履行package script
咱们能够运用lerna run
指令,去运行每个包中包括有相关package script的相关指令。
例如,咱们有两个前端package,里边的package.json中都有一个start
{
"srcipts": {
"start": "react-scripts start",
}
}
咱们则能够直接运行
lerna run --parallel start
--parallel
参数便是指为项目的中需求一向的进程,打印一切子进程的输出。说得有点绕,理解为需求一向运行的就加上这个参数就能够了。
包依靠
装置包
运用下面指令,能够装置一切包的package.json
中的dependencies
npx lerna bootstrap
公共的包
咱们能够将公共的包装置在根目录下的package.json
下,例如,你是前端微服务的项目并且是运用react作为主要技术栈的,能够把react
、react-dom
等装置在根目录下,packages都是能够直接引证的
更常用的是一些项目标准的装备,例如eslint
、prettier
、tsconfig
之类的,也能够直接装置在根目录下
把公共包提取出来的好处有:
- 一切包用的依靠包版别都是一致的
- 做一些包的晋级和像github进行包检查时,更方便地进行晋级
- 装置依靠包的时间能够更少
- 需求更少的存储空间
项目中包与包之间的引证
假如咱们packages里边需求进行互相引证
咱们运用lerna add
指令,能够为指定的包装置第三方的或许本地的包,这个指令和yarn add
或许npm install
实质上是类似的,下面是一些来自文档的一些例子
# Adds the module-1 package to the packages in the 'prefix-' prefixed folders
lerna add module-1 packages/prefix-*
# Install module-1 to module-2
lerna add module-1 --scope=module-2
# Install module-1 to module-2 in devDependencies
lerna add module-1 --scope=module-2 --dev
# Install module-1 to module-2 in peerDependencies
lerna add module-1 --scope=module-2 --peer
# Install module-1 in all modules except module-1
lerna add module-1
# Install babel-core in all modules
lerna add babel-core
版别操控
lerna的版别操控依靠于相应git branch上面的tag,来判断修正记录和进行相应的版别操控
这里一开端踩了坑,lerna是不支持git flow的,作者认为假如按照git flow的话,是一种anti-pattern,也便是反例。
相关的issue:github.com/lerna/lerna…
由于咱们运用的是independent mode,所以咱们需求对每个包的版别进行办理。假如项目运用了一些CI workflow的话,咱们还需求将版别操控放到CI流程中去。
lerna进行版别操控的话,是运用lerna version
指令。
详细做了几个事情:
- 界说了从上一个git branch release tag开端,哪些包被更新了
- 更新版别号
- 修正包的
package.json
里边的version
, 运行在根目录下和每个更新包中的npm lifecycle scripts。提交这些修正,并打上release tag - 推送到长途git repository
因而,lerna现已能为咱们完结打release tag和更新changelog的作业。
最终,依据git flow,咱们只需求将release分支合并回development分支,依据需求看是否需求hotfix release的代码,然后在合并到master/main分支,则完结了一次release
假如你需求有prerelease、beta的,也是类似的进行版别操控。lerna version
供给了参数能够完结
-
--conventional-prerelease
: 当时release是prerelease版别. -
--conventional-graduate
: 把prerelease版别的包变成安稳版别的包版别.
办理发布
最终,假如咱们还需将包发布到npm或许其他registry上面,则需求用到lerna publish
指令。
留意,假如你不是一切包都需求发布,能够在不需求发布的包中把
package.json
的private
设为true
publish指令有两种状况可选
# 发布在当时commit head下,被打了tag的包
lerna publish from-git
# 发布在当时npm registry下,没有该版别的包
lerna publish from-package
在publish的时候,有一个比较重要的参数--canary
。
这个参数的意思是,在发布到npm之前,先在当时版别创立一个新版别,将minor版别加上1,还有加上alpha后缀,例如1.0.0会变成1.1.0-alpha)。假如需求指定后缀,则能够运用--preid
参数进行界说,例如--preid beta
总结
至此,咱们现已介绍了lerna假如创立一个简单的monorepo的项目,并进行脚本运行,包的装置和依靠,版别操控和发布。
剩下的交给你们。