0

Lerna 基本概念

 2 years ago
source link: https://segmentfault.com/a/1190000040444877
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Lerna 基本概念

最近工作上要接触相关的东西,开始熟悉文档,进行相关翻译记录,方便以后查阅。

基于 Lerna 版本 : v3.22.1 。

21-logo

Lerna 是一个管理有多个包的 JavaScript 项目的工具。

将大的代码库分成独立版本的包,对于代码共享,是非常有用的。然而,在许多存储库中进行修改,会变混乱和难以跟踪,跨库的测试,很快会变的复杂。

为了解决这些(和很多其它)问题,一些项目将会把他们的代码库组织成多个包的存储库(有些时候称为 monorepos)。像 Babel, React, Angular, Ember, Meteor, Jest 等其它很多项目开发时,都在一个存储库下开发所有的包。

Lerna 是一个通过 git 和 npm 来优化管理多包存储库的工作流的工具。

Lerna 也可以减少在开发和构建环境中,许多包副本对时间和空间的需要,通常一个项目的下载分成了很多个独立的 NPM 包。详情见 hoist 文档。

一个 Lerna 库是什么样子?

实际上没什么。一个类似下面样子的文件系统:

my-lerna-repo/
  package.json
  packages/
    package-1/
      package.json
    package-2/
      package.json

Lerna 能做什么?

Lerna 两个基本的的命令是:lerna bootstraplerna 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.json
  lerna.json

是如何运作

Lerna 允许你管理项目时,使用两种模式中的一种:FixedIndependent

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 展示出来吧:

[![lerna](https://img.shields.io/badge/maintained%20with-lerna-cc00ff.svg)](https://lerna.js.org/)

如果你更喜欢命令行引导的方式,你可能喜欢 lerna-wizard 。它将会通过进行一系列已经定义好的步骤引导你:

21-cli-guide


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK