Lerna --多包存储管理工具(一)

lerna

最近在看[vue-cli](https://github.com/vuejs/vue-cli的源码部分,注意到这一个仓库下维护了多个package,很好奇他是如何在一个repo中管理这些package的。

我们组现在也在使用组件库的方式维护项目间共用的业务代码。有两个组件库,存在依赖的关系,目前联调是通过npm link的方式,性能并不好,时常出现卡顿的问题。加上前一段时间组内分享vue3也提到了lerna,于是便决定仔细的调研一下这个工具,为接下里的组件库优化助力。

lerna的文档还是很详细的,因为全是英文的,考虑到阅读问题,这里我先是自己跑了几个demo,然后做了中文翻译。后续我会出一篇专门的lerna实战篇

[demo](https://github.com/qinzhiwei1993/lerna-repo-test

lerna 是干什么的?

Lerna 是一个工具,它优化了使用 git 和 npm 管理多包存储库的工作流。

背景

1.将一个大的 package 分割成一些小的 packcage 便于分享,调试

2.在多个 git 仓库中更改容易变得混乱且难以跟踪

3.在多个 git 仓库中维护测试繁琐

两种工作模式

Fixed/Locked mode (default)

vue,babel 都是用这种,在 publish 的时候,所有的包版本都会更新,并且包的版本都是一致的,版本号维护在 lerna.jon 的 version 中

Independent mode

lerna init --independent

独立模式,每个 package 都可以有自己的版本号。版本号维护在各自 package.json 的 version 中。每次发布前都会提示已经更改的包,以及建议的版本号或者自定义版本号。这种方式相对第一种来说,更灵活

初始化项目


npm install -g lerna // 这里是全局安装,也可以安装为项目开发依赖,使用全局方便后期使用命令行

mkdir lerna-repo

cd lerna-repo

lerna init // 初始化一个lerna项目结构,如果希望各个包使用单独版本号可以加 -i | --independent

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-znl8Z0YA-1599646450309)(https://github.com/qinzhiwei1993/lerna-repo-test/raw/master/images/[email protected])]

标准的 lerna 目录结构

  • 每个单独的包下都有一个 package.json 文件

  • 如果包名是带 scope 的,例如@test/lerna,package.json 中,必须配置"publishConfig": {“access”: “public”}


my-lerna-repo/

    package.json

    lerna.json

    LICENSE

    packages/

        package-1/

            package.json

        package-2/

            package.json

启用 yarn Workspaces (强烈建议)

Workspaces can only be enabled in private projects.

默认是 npm, 每个子 package 下都有自己的 node_modules,通过这样设置后,会把所有的依赖提升到顶层的 node_modules 中,并且在 node_modules 中链接本地的 package,便于调试

注意:必须是 private 项目才可以开启 workspaces


// package.json

"private": true,

"workspaces": [

    "packages/*"

],
 

// lerna.json

 
"useWorkspaces": true,

"npmClient": "yarn",

hoist: 提取公共的依赖到根目录的node_moduels,可以自定义指定。其余依赖安装的package/node_modeles中,可执行文件必须安装在package/node_modeles

workspaces: 所有依赖全部在跟目录的node_moduels,除了可执行文件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Wk3liN9K-1599646450317)(https://github.com/qinzhiwei1993/lerna-repo-test/raw/master/images/[email protected])]

常用命令

lerna init

初始化 lerna 项目

  • -i, --independent 独立版本模式

lerna create [loc]

创建一个 packcage

  • --access 当使用scope package时(@qinzhiwei/lerna),需要设置此选项 [可选值: “public”, “restricted”][默认值: public]

  • --bin 创建可执行文件 --bin <executableName>

  • --description 描述 [字符串]

  • --dependencies 依赖,用逗号分隔 [数组]

  • --es-module 初始化一个转化的Es Module [布尔]

  • --homepage 源码地址 [字符串]

  • --keywords 关键字数 [数组]

  • --license 协议 [字符串][默认值: isc]

  • --private 是否私有仓库 [布尔]

  • --registry 源 [字符串]

  • --tag 发布的标签 [字符串]

  • -y, --yes 跳过所有的提示,使用默认配置 [布尔]

lerna add

为匹配的 package 添加本地或者远程依赖,一次只能添加一个依赖


$ lerna add <package>[@version] [--dev] [--exact] [--peer]

运行该命令时做的事情:

  1. 为匹配到的 package 添加依赖

  2. 更改每个 package 下的 package.json 中的依赖项属性

Command Options

以下几个选项的含义和npm install时一致

  • --dev

  • --exact

  • --peer 同级依赖,使用该package需要在项目中同时安装的依赖

  • --registry <url>

  • --no-bootstrap 跳过 lerna bootstrap,只在更改对应的 package 的 package.json 中的属性

所有的过滤选项都支持

Examples


# 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 bootstrap

将本地 package 链接在一起并安装依赖

执行该命令式做了一下四件事:

1.为每个 package 安装依赖

2.链接相互依赖的库到具体的目录,例如:如果 lerna1 依赖 lerna2,且版本刚好为本地版本,那么会在 node_modules 中链接本地项目,如果版本不满足,需按正常依赖安装

3.在 bootstraped packages 中 执行 npm run prepublish

4.在 bootstraped packages 中 执行 npm run prepare

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ENY4EVrV-1599646450349)(https://github.com/qinzhiwei1993/lerna-repo-test/raw/master/images/[email protected])]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DVSIBjOD-1599646450351)(https://github.com/qinzhiwei1993/lerna-repo-test/raw/master/images/[email protected])]

Command Options
  • --hoist 匹配 [glob] 依赖 提升到根目录 [默认值: ‘**’], 包含可执行二进制文件的依赖项还是必须安装在当前 package 的 node_modules 下,以确保 npm 脚本的运行

  • --nohoist 和上面刚好相反 [字符串]

  • --ignore-prepublish 在 bootstraped packages 中不再运行 prepublish 生命周期中的脚本 [布尔]

  • --ignore-scripts 在 bootstraped packages 中不再运行任何生命周期中的脚本 [布尔]

  • --npm-client 使用的 npm 客户端(npm, yarn, pnpm, …) [字符串]

  • --registry 源 [字符串]

  • --strict 在 bootstrap 的过程中不允许发出警告,避免花销更长的时间或者导致其他问题 [布尔]

  • --use-workspaces 启用 yarn 的 workspaces 模式 [布尔]

  • --force-local 无论版本范围是否匹配,强制本地同级链接 [布尔]

  • --contents 子目录用作任何链接的源。必须适用于所有包 [字符串][默认值: .]

lerna link

将本地相互依赖的 package 相互连接。例如 lerna1 依赖 lerna2,且版本号刚好为本地的 lerna2,那么会在 lerna1 下 node_modules 中建立软连指向 lerna2

Command Options
  • –force-local 无论本地 package 是否满足版本需求,都链接本地的

// 指定软链到package的特定目录

"publishConfig": {
   

    "directory": "dist" // bootstrap的时候软链package下的dist目录 package-1/dist => node_modules/package-1

}

lerna list

list 子命令
  • lerna ls: 等同于 lerna list本身,输出项目下所有的 package

  • lerna ll: 输出项目下所有 package 名称、当前版本、所在位置

  • lerna la: 输出项目下所有 package 名称、当前版本、所在位置,包括 private package

Command Options

所有的过滤选项都支持

--json

以 json 形式展示


$ lerna ls --json

[

    {

        "name": "package-1",

        "version": "1.0.0",

        "private": false,

        "location": "/path/to/packages/pkg-1"

    },

    {

        "name": "package-2",

        "version": "1.0.0",

        "private": false,

        "location": "/path/to/packages/pkg-2"

    }

]

--ndjson

newline-delimited JSON展示信息


$ lerna ls --ndjson

{"name":"package-1","version":"1.0.0","private":false,"location":"/path/to/packages/pkg-1"}

{"name":"package-2","version":"1.0.0","private":false,"location":"/path/to/packages/pkg-2"}

--all

Alias: -a

显示默认隐藏的 private package


$ lerna ls --all

package-1

package-2

package-3 (private)

--long

Alias: -l

显示包的版本、位置、名称


$ lerna ls --long

package-1 v1.0.1 packages/pkg-1

package-2 v1.0.2 packages/pkg-2

  

$ lerna ls -la

package-1 v1.0.1 packages/pkg-1

package-2 v1.0.2 packages/pkg-2

package-3 v1.0.3 packages/pkg-3 (private)

--parseable

Alias: -p

显示包的绝对路径

In --long output, each line is a :-separated list: <fullpath>:<name>:<version>[:flags..]


$ lerna ls --parseable

/path/to/packages/pkg-1

/path/to/packages/pkg-2

  

$ lerna ls -pl

/path/to/packages/pkg-1:package-1:1.0.1

/path/to/packages/pkg-2:package-2:1.0.2

  

$ lerna ls -pla

/path/to/packages/pkg-1:package-1:1.0.1

/path/to/packages/pkg-2:package-2:1.0.2

/path/to/packages/pkg-3:package-3:1.0.3:PRIVATE

--toposort

按照拓扑顺序(dependencies before dependents)对包进行排序,而不是按目录对包进行词法排序。


$ json dependencies <packages/pkg-1/package.json

{

    "pkg-2": "file:../pkg-2"

}

  

$ lerna ls --toposort

package-2

package-1

--graph

将依赖关系图显示为 JSON 格式的邻接表 adjacency list.


$ lerna ls --graph

{

    "pkg-1": [

        "pkg-2"

    ],

    "pkg-2": []

}

  

$ lerna ls --graph --all

{

    "pkg-1": [

       "pkg-2"

    ],

    "pkg-2": [

        "pkg-3"

    ],

    "pkg-3": [

        "pkg-2"

    ]

}

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值