简介
Lerna 是一种工具,针对 使用 git 和 npm 管理多软件包代码仓库的工作流程进行优化。 多包管理器
背景
当前手上需要同时维护几个npm工具包,有些包与包之间存在依赖管理。 经常更新某个底层包后,需要同时更新上层包。 维护的心智负担着实不小。所以希望通过 lerna 多包管理器,提高npm包的维护效率。
- lerna 4.0.0
DEMO 目录
- root/
- lerna.json lerna 配置
- package.json
- packages/ npm包集合
- pkg-ts npm 子包
- pkg-es6
安装
代码语言:javascript复制npm i -g lerna
初始化
首先进入根目录, 调用初始化命令init 。 lerna 将为我们生成基础的项目目录和配置.
代码语言:javascript复制lerna init
image.png
模式
lerna 对包的有两种处理模式, 固定模式 独立模式
- 固定模式
管理下的所有包使用 lerna.json 的统一版本线。 例如我们存在包 A: v1.0.0 , b: v2.0.0 lerna.json v1.0.0。 发布新版本时,更新版本为v1.1.0。 A , B , lerna.json 的版本号都将统一为 v1.1.0。 这里模式适合,包集合统一依赖,包集合作为整体工具来使用
- 独立模式
与固定模式相反, 独立模式允许各个包独立管理自己的版本。 此时 lerna.json 中的 version 字段值为 "independent"
- 模式设置
// 方式一 初始化时, 添加 -i 或 --independent 参数
lerna init -i
代码语言:javascript复制// 方式二 直接配置lerna.json
// lerna.json
{
...
"version": "independent"
}
配置文件
lerna.json 配置文件中,我们设置详细的自定义配置。
代码语言:javascript复制{
// 统一版本号,
"version": "0.0.0",
// 包管理工具类型, npm, yarn, cnpm, 之后的命令将使用该配置, 例如依赖安装
"npmClient": "npm",
// 包目录, 可以指定多个目录或目录匹配规则。
"packages": [
"packages/*" // 需要管理的包都放在 packages/ 目录下
],
// 是否开启"工作空间"
"useWorkspaces": false,
// 命令行配置
// 调用命令行时,将合并该配置内容执行相关命名
// 命令可配置项于命令行一一对应
"command": {
// 命令名称
"bootstrap": {
// 命令参数名: 参数值
"ignore": "component-*",
// 等价于命令 lerna bootstrap --ignore=component-*
}
...
}
}
配置文件可以认为保存我们经常使用的命令操作配置,简化使用。命令使用及配置查看 基础命令, 进阶命令
基础命令
学lerna 主要学习的是lerna 常用管理命令, 例如 依赖安装,版本管理,发包等。
init 初始化
用来初始化lerna 项目
代码语言:javascript复制lerna init
参数:
- -i or --independent 使用独立模式, 默认固定模式
- --exact 使用固定模式
create 创建包
将在包集合目录下,新建包基础目录结构 lerna create [名称] [集合目录]
代码语言:javascript复制lerna create utils
参数:
- name 名称
- loc 包集合目录, 单一包集合时为可选。
// leran.json
{
"packages": [
// 存在多个包集合
"source/*",
"utils/*",
]
}
// shell // 在指定包集合中新增day包 lerna create day utils
- -- yes 跳过交互配置
learna create day --yes
- --bin 是否为可执行包
- --description 包描述
- --dependencies 依赖列表
- --es-module 初始化为ES6 模块
- --homepage 包首页地址
- --keywords npm 查询关键子列表
- --license 开源许可
- --private 私有包
- --registry npm源
- --tag 标签
lerna create day --description=一段描述
boostrap 安装依赖
为所有包安装依赖, 并链接相关的本地依赖包。
代码语言:javascript复制lerna boostrap
参数:
- --ignore 忽略
安装时,跳过某些包的依赖安装。lerna bootstrap --ignore [包命|包命匹配规则] 这里的包命指的是 package.json 中 name 属性定义的包名
代码语言:javascript复制// 不为 pkg-ts 安装依赖
lerna bootstrap --ignore pkg-ts
// 不为 以 pkg- 开头的包安装依赖
lerna bootstrap --ignore pkg-*
- --hoist 提升
正常情况下, 依赖安装在对应的包目录下。有时候多个包有相同的依赖或我们希望依赖相同的包实例, 可以将依赖包安装到根目录。
代码语言:javascript复制lerna bootstrap --hoist
- --nohoist
依赖提升时,忽略部分包, --nohoist=[依赖包名 | 依赖包命匹配规则]
代码语言:javascript复制// 依赖提升,但不提升babe依赖
lerna bootstrap --hoist --nohoist=babel-*
- --strict 严格模式
相同依赖包的版本不兼容时,将报错并终止安装
代码语言:javascript复制lerna bootstrap --hoist --strict
- --ignore-scripts
忽略生命周期钩子的调用
代码语言:javascript复制lerna bootstrap --ignore-scripts
- --npm-client
包管理工具类型
// 使用 yarn 安装依赖 lerna bootstrap --npm-client=yarn
- --use-workspaces
开启workspaces
代码语言:javascript复制lerna bootstrap --use-workspaces
同时需要在根目录package.json 配置 workspaces
代码语言:javascript复制// root/package.json
{
"workspaces": ["packages/*"]
}
- --force-local
始终使用本地依赖,无论版本是否匹配
代码语言:javascript复制lerna bootstrap --force-local
- --no-ci / --ci
npm ci 开启or关闭
代码语言:javascript复制lerna bootstrap --no-ci
or
lerna bootstrap --ci
clean
清理所有依赖, 删除所有包内node_modules
代码语言:javascript复制lerna clean
参数:
- --yes
不做确认提示
代码语言:javascript复制lerna clean --yes
list
显示包列表
代码语言:javascript复制lerna list
// or
lerna ls
参数
- --json
以json的形式显示
- --all | -a
显示所有包,包括私有包
- --long | -l
显示扩展信息
- --parseable
显示包路径列表
- --toposort
按照依赖关系显示
- --graph
按照依赖关系以json形式显示
进阶命令
publish
发包
代码语言:javascript复制learn publish
参数:
- form-git
根据 git commit 的 annotaed tag 确定包版本,进行发包
代码语言:javascript复制lerna publish from-git
- from-package
根据 package.json 的版本,进行发包
代码语言:javascript复制lerna publish from-package
- --canary
根据上次版本计算出新的版本号,进行发包。 不会进入版本交互模式中
代码语言:javascript复制lerna publish --canary
- --contents <dir>
指定发布的包内容, 类似 package.json 的 files 属性
代码语言:javascript复制lern publish --contents lib
- --dist -tag
新增 dist-tag 标签
代码语言:javascript复制lerna publish --dist-tag next
- --no-verify-access
禁止npm权限校验
代码语言:javascript复制lerna publish --no-verify-access
- --preid
为--canary 提供指定的发布标识符
代码语言:javascript复制lerna publish --canary
# uses the next semantic prerelease version, e.g.
# 1.0.0 => 1.0.1-alpha.0
lerna publish --canary --preid next
# uses the next semantic prerelease version with a specific prerelease identifier, e.g.
# 1.0.0 => 1.0.1-next.0
- --pre-dist-tag
--dist-tag 的预发布版本
代码语言:javascript复制lerna publish --pre-dist-tag next
- --registry
使用指定源发布
代码语言:javascript复制lerna publish --registry https://cnpmjs.org
- --tag-version-prefix
自定义版本前缀, 默认: v
代码语言:javascript复制# locally
lerna version --tag-version-prefix=''
# on ci
lerna publish from-git --tag-version-prefix=''
- --ignore-scripts
禁用生命周期钩子脚本
代码语言:javascript复制lerna publish --ignory-scripts
- --yes
跳过确认
代码语言:javascript复制lerna publish --canary --yes
add
安装包, 类似 npm i package,
代码语言:javascript复制// 为所有包安装 dayjs 依赖
lerna add dayjs
参数:
- --scope
限制安装范围
代码语言:javascript复制// 只为包 pkg-1 安装依赖 dayjs
lerna add dayjs --scope=pkg-1
// 等价于 cd pkg-1/ && npm i dayjs
- --dev
开发依赖
代码语言:javascript复制lerna add rollup --dev
- --exact
使用精确版本,而不是版本范围。
例如 默认添加版本号: ^1.0.1, 精确版本: 1.0.1
lerna add --exact
- --peer
添加到 peerDependencies 中
代码语言:javascript复制lerna add vue --peer
- --registry <url>
使用指定源安装
代码语言:javascript复制lerna add vue --registry http://r.npm.taobao.org/
- --no-bootstrap
跳过 bootstrap
代码语言:javascript复制lerna add rollup
version
创建新的包版本 执行流程:
- 标识自上次标记发布以来已更新的包。
- 新版本的提示。
- 修改包元数据,执行各个包内的生命周期钩子。
- 提交修改和标签。
- 推送到 git 远端分支。
lerna version
参数
- bump
版本更新方式
- major 主版本
- mior 副版本
- patch 修复版本
- premajor 预发布主版本
- preminor 预发布副版本
- prepatch 预发布修复版本
- prerelease 预发布版
参数: @lerna/version(翻译
run
指定package.json 脚本命令
代码语言:javascript复制lerna run build
参数:
- --stream
显示子进程输出
代码语言:javascript复制lerna run <命令> --stream
- --parallel
显示子进程输出, 忽略排序
代码语言:javascript复制lerna run <命令> --parallel
- --no-bail
禁止非零退出
代码语言:javascript复制lerna run --no-bail test
- --no-prefix
禁止包前缀
代码语言:javascript复制lerna run --no-prefix
- --profile
生成性能分析文件
代码语言:javascript复制lerna run build --profile
- --profile-localtion <path>
生成并保存性能分析文件
代码语言:javascript复制lerna run build --profile-localtion
exec
在每个包中,执行命令行, run 命令的底层命令
代码语言:javascript复制lerna exec -- echo xx > logs.text
- --scope
限制命令作用范围
代码语言:javascript复制lerna exec --scope <包名> -- cd ./src
- --stream
显示命令输出, 带包前缀
代码语言:javascript复制lerna exec --scope localPackage -- ls
- --parallel
显示命令输出, 忽略排序
代码语言:javascript复制lerna exec --parallel localPageck -- ls
- --no-bail
禁止非零退出
代码语言:javascript复制lerna exec --nobail ...
- --no-prefix
禁止包前缀
代码语言:javascript复制lerna exec --no-prefix
- --profile
生成性能分析文件
代码语言:javascript复制lerna exec --profile
- --profile-localtion <location>
生成并保存性能分析文件
代码语言:javascript复制lerna exec --profile --profile-location=logs/profile/ -- <command>
import
导入外部独立包, 例如我们之前为使用lerna 管理的独立npm包, 导入到lerna项目包集合后, 可以使用改目录导入相关 git 记录等
代码语言:javascript复制lerna import <包地址>
参数:
- --faltten
lerna import ./package --flatten
- --dest
根据 lerna.json 指定导入的目录
代码语言:javascript复制// lerna.json
{
"packages": [
"pakcages/*",
"utils/*"
]
}
// 执行导入
lerna import ../out-pkg --dest=utils
// out-pkg 将被导入utils目录下
- --preserve-commit
保留原git 提交者信息以及时间
代码语言:javascript复制lerna import ../out-pkg --preserve-commit
changed
显示下次将发布的包列表, 一般是包版本发生变化
代码语言:javascript复制lerna changed
命令参数于 list 命令相同。
- --json
- --ndjson
- -a --all
- -l --long
- -p --parseable
- --toposort
- --graph
diff
显示包修改内容, 类似 git diff
代码语言:javascript复制lerna diff
info
显示环境信息
代码语言:javascript复制lerna info
问题
- 发布时git add 失败
这里我在.gitignore 中忽略了, 版本锁文件。 package-lock.json。 造成git add 发生冲突
参考文档
- 深入 lerna 发包机制 —— lerna publish-技术圈
- @lerna/version(翻译)
- @lerna/publish(翻译)
- 深入 lerna 发包机制 —— lerna version