Lerna 基本概念
引子
最近工作上要接触相关的东西,开始熟悉文档,进行相关翻译记录,方便以后查阅。
基于 Lerna 版本 : v3.22.1 。
Lerna 是一个管理有多个包的 JavaScript 项目的工具。
- Origin
- My GitHub
关于
将大的代码库分成独立版本的包,对于代码共享,是非常有用的。然而,在许多存储库中进行修改,会变混乱和难以跟踪,跨库的测试,很快会变的复杂。
为了解决这些(和很多其它)问题,一些项目将会把他们的代码库组织成多个包的存储库(有些时候称为 monorepos)。像 Babel, React, Angular, Ember, Meteor, Jest 等其它很多项目开发时,都在一个存储库下开发所有的包。
Lerna 是一个通过 git 和 npm 来优化管理多包存储库的工作流的工具。
Lerna 也可以减少在开发和构建环境中,许多包副本对时间和空间的需要,通常一个项目的下载分成了很多个独立的 NPM 包。详情见 hoist 文档。
一个 Lerna 库是什么样子?
实际上没什么。一个类似下面样子的文件系统:
my-lerna-repo/package.jsonpackages/package-1/package.jsonpackage-2/package.json
Lerna 能做什么?
Lerna 两个基本的的命令是:lerna bootstrap
和 lerna publish
。
bootstrap
会将库中的依赖联系起来。publish
将发布任何更新的包。
Lerna 不能做什么?
Lerna 不是无服务器 monorepos 的部署工具。Hoisting 可能与传统的无服务器 monorepos 部署技术不兼容。
开始
下面的介绍适用于 3.x 版本的 Lerna。对于一个新项目,我们推荐使用这个版本取代 2.x 版。
让我们从通过 npm 安装 Lerna 作为你项目 dev 依赖开始。
$ mkdir lerna-repo && cd $_
$ npx lerna init
这将会创建一个 lerna.json
配置文件和一个 package
文件夹,所以你的文件夹现在看起来应该是这样的:
lerna-repo/packages/package.jsonlerna.json
是如何运作
Lerna 允许你管理项目时,使用两种模式中的一种:Fixed 或 Independent。
Fixed/Locked 模式 (默认)
Fixed 模式的 Lerna 项目,它的操作是在一条版本线上。这个版本保存在 lerna.json
文件中的 version
属性上,这个文件在你项目的根目录下。当你运行 lerna publish
,如果一个模块从上个发布之后已经有了更新,它将会更新到你发布的一个新版本上。这意味着当你需要时才发布一个包的新版本。
注意:如果你有一个 0 主要版本(例如 0.y.z),所有的更新被认为是破坏性的。由于这个,运行
lerna publish
伴随着 0 主要版本并选择任何非预发布版本数字,将会导致所有的包发布新的版本,即使从上个发布之后,并不是所有的包都发生过变化。
这个就是 Babel 目前使用的模式。如果你想将所有包的版本自动归到一起,那就使用这个模式。这种模式的一个问题是:任何包的重大更改都将导致所有的包都具有对应新的版本。
Independent 模式
lerna init --independent
Independent 模式的 Lerna 项目允许维护者提升每个包各自的版本。每次你发布,你将会受到针对每个已更改包的提示,以指定它是补丁(patch)、小更改(minor)、大更改(major )还是自定义(custom)更改。
Independent 模式允许你具体的更新每个包的版本,这个对于一组组件很有帮助。这种模式结合一些类似 semantic-release 的东西,将会减少很多麻烦。(atlassian/lerna-semantic-release 已经在这么做了)。
在 independent 模式下运行时,需将 lerna.json 文件中的 version 字段的值设置为 independent 。
已解决的问题
如果你在使用 Lerna 时发生任何问题,请在这个文档里面查看一下,可能会有你想要的答案。
常见问题
见 FAQ.md 。
概念
当 Lerna 运行触发一个错误时,它会生成一个 lerna-debug.log
文件(跟 npm-debug.log
文件一样)。
Lerna 也支持 scoped packages。
运行 lerna --help
可以看到所有可用的命令和选项。
lerna.json
{"version": "1.1.3","npmClient": "npm","command": {"publish": {"ignoreChanges": ["ignored-file", "*.md"]},"bootstrap": {"ignore": "component-*","npmClientArgs": ["--no-package-lock"]}},"packages": ["packages/*"]
}
version
: 当前库的版本。npmClient
: 指定特定客户端来运行命令的选项(还可以根据每个命令指定)。如果想用 yarn 运行所有的命令,就把这个值修改为"yarn"
。默认是 “npm”。command.publish.ignoreChanges
: 全局数组,里面指定文件的改动将不会包含在lerna changed/publish
中。使用这个是为了阻止一些对不必要的修改进行发布,例如修改README.md
。command.publish.message
: 当发布版本时自定义提交信息。更多信息见 @lerna/version 。command.publish.registry
: 使用这个设置自动发布源,如果需要认证,必须要先进行认证。command.bootstrap.ignore
: 全局数组,里面指定的内容,当运行lerna bootstrap
命令时,将不会进行关联。command.bootstrap.npmClientArgs
: 一组参数的全局数组,在运行lerna bootstrap
命令时,直接传递给npm install
命令的参数。command.bootstrap.scope
: 一个全局数组,用于限制运行lerna bootstrap
命令时将引导哪些包。packages
: 用作包的位置的全局数组。
在 lerna.json
里包的配置是匹配包含 package.json
文件的目录的全局变量列表,这也是 lerna 如何组织 “叶子” 包的方式(相对的,“根”的 package.json
,是为了管理整个库的 dev 依赖和脚本)。
默认的,lerna 初始化包列表为 ["packages/*"]
,但是你也可以使用另外一个目录例如 ["modules/*"]
,或者 ["package1", "package2"]
。全局的定义是相对于 lerna.json
文件所在的目录,通常是库的根目录。唯一的限制就是你不能够直接嵌套包的位置,这个也是“标准” npm 包共有的限制。
例如,["packages/*", "src/**"]
匹配这个树结构:
packages/
├── foo-pkg
│ └── package.json
├── bar-pkg
│ └── package.json
├── baz-pkg
│ └── package.json
└── qux-pkg└── package.json
src/
├── admin
│ ├── my-app
│ │ └── package.json
│ ├── stuff
│ │ └── package.json
│ └── things
│ └── package.json
├── profile
│ └── more-things
│ └── package.json
├── property
│ ├── more-stuff
│ │ └── package.json
│ └── other-things
│ └── package.json
└── upload└── other-stuff└── package.json
把叶子包放在 packages/*
下被认为是最佳实践,但并不是使用 Lerna 的必需条件。
弃用字段
lerna.json
中的一些字段已经不支持使用了,包含:
lerna
: 之前是用来指定 Lerna 当前的版本,在 V3 中已经弃用和删除了。
公用 devDependencies
大多数 devDependencies
都可以通过 lerna link convert
放到 Lerna 库的根部。
上面的命令将自动提升并使用 file:
说明符。
提升有下面的一些好处:
- 所有的包使用提供依赖的版本一致。
- 可以使用自动化工具保持根部依赖是最新的版本,例如 GreenKeeper。
- 安装依赖的时间减少了。
- 减少了占据的存储空间。
注意,提供 npm 脚本使用的“二进制”可执行文件的 devDependencies
仍然需要直接安装在使用它们的每个包中。
例如 nsp
是在执行 lerna run nsp
时所必需的依赖。
{"scripts": {"nsp": "nsp"},"devDependencies": {"nsp": "^2.3.3"}
}
Git 提升依赖
Lerna 可以通过在 git remote url 上带 committish
(例如 #v1.0.0
或者 #semver:^1.0.0
)来指定本地依赖的版本,取代常指定的版本数字范围。当包必须是私有的并且不需要私有的 npm 注册表时,允许通过 Git 存储库分发包。(有关实现的详细信息,参考这个说明)
请注意,Lerna 不会将 git 历史实际拆分为单独的只读存储库。这是用户的责任。
// packages/pkg-1/package.json
{name: "pkg-1",version: "1.0.0",dependencies: {"pkg-2": "github:example-user/pkg-2#v1.0.0"}
}// packages/pkg-2/package.json
{name: "pkg-2",version: "1.0.0"
}
在上面的例子中:
lerna bootstrap
命令将正确的将pkg-2
链接到pkg-1
中。- 当
pkg-2
改变,lerna publish
命令将更新 committish (#v1.0.0
) 到pkg-1
中。
README Badge
使用 Lerna ?添加一个 README Badge 展示出来吧:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dv5E59ha-1627951931430)(https://img.shields.io/badge/maintained%20with-lerna-cc00ff.svg)]
[![lerna](https://img.shields.io/badge/maintained%20with-lerna-cc00ff.svg)](https://lerna.js.org/)
向导
如果你更喜欢命令行引导的方式,你可能喜欢 lerna-wizard 。它将会通过进行一系列已经定义好的步骤引导你:
参考资料
- lerna github
Lerna 基本概念相关推荐
- 【Lerna 基本使用】
现代前端工程化-彻底搞懂基于 Monorepo 的 lerna 模块(从原理到实战)lerna是什么?有什么优势? lerna 基础概念 翻译:Lerna是一个用来优化托管在 git\npm 上的多 ...
- 现代前端工程化-基于 Monorepo 的 lerna 模块(从原理到实战)
本文你能学到什么? 看完本文后希望可以检查一下图中的内容是否都掌握了,文中的例子最好实际操作一下,下面开始正文. 本文是前端工程化系列中的一篇,回不断更新,下篇更新内容可看文末的下期预告!宗旨:工程化 ...
- Lerna 运行流程剖析
大家好,我是若川.持续组织了6个月源码共读活动,感兴趣的可以点此加我微信 ruochuan12 参与,每周大家一起学习200行左右的源码,共同进步.同时极力推荐订阅我写的<学习源码整体架构系列& ...
- 基于pnpm + lerna + typescript的最佳项目实践 - 理论篇
本文来自作者@金虹桥程序员 投稿 原文链接:https://juejin.cn/post/7043998041786810398 本系列文章分为两篇:理论篇和实践篇 理论篇:介绍pnpm(pnpm的特 ...
- 基于 Lerna 管理 packages 的 Monorepo 项目最佳实践
对于维护过多个package的同学来说,都会遇到一个选择题,这些package是放在一个仓库里维护还是放在多个仓库里单独维护,本文通过一个示例讲述了如何基于Lerna管理多个package,并和其它工 ...
- lerna + yarn workspaces 使用备忘
CSDN 中文章不一定能及时更新,欢迎点击前往我的博客查看最新版本:许盛的博客 最近学了不少组件化相关的知识,需要编写一些 cli 工具.公共组件之类的,和以往大量的做业务项目,走 CI/CD 容器化 ...
- 如何使用lerna管理你的仓库
如何使用lerna管理你的仓库 multirepo VS monorepo 在介绍我们今天的主角 lerna 之前,首先了解下什么是 multirepo ?什么是 monorepo ? multire ...
- lerna管理多项目
介绍: 公司有多个项目,每个项目有相同的依赖,或者相同的配置.依赖重复安装,多个依赖可能在多个仓库中存在不同的版本,磁盘空间占用高,开发效率也较低.每个项目都会有一个git仓库独立管理,多个项目来回切 ...
- 使用lerna构建monorepo
使用lerna构建monorepo monorepo是什么? monorepo就是在一个git repository里面管理多个packages或者项目 在实际开发使用中,在哪些场景下可能你会想要使用 ...
最新文章
- 摄像头Camera标定Calibration原理Theory
- H5与Native交互之JSBridge技术
- Cassandra1.2文档学习(7)—— 规划集群部署
- SQLyog中文乱码的解决方法
- 【 Element UI 】—Element UI 的基本使用
- 系统学习机器学习之线性判别式(二)
- 狂神说springboot源码_狂神说SpringBoot04:JSR303数据校验及多环境切换
- 8产权界定_保护与限制
- (VCIP-2018)基于选择性卷积特征的广义均值池化细粒度图像检索
- 手机格式化的计算机原理,格式化也不靠谱?教你如何彻底删除手机上的数据
- matlab计算图像的曲率半径
- B. Shifting Sort- Codeforces Round #744 (Div. 3)
- 苹果 WWDC21 发布会全汇总,iOS 15更个性化,全家桶协作更有生产力
- 波卡平行链生态一览|Polkadot Decoded 回顾
- 【NOI题库】【NOIP2016PJ猜题】雇佣兵
- MySQL索引的底层数据结构衍变史
- ffmpeg批量转换m4a为mp3
- nodejs.ReferenceError:window is not defined
- 如何为新员工找到团队“归属感”
- Kernel Knights (Gym - 101480K)