乐趣区

关于javascript: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.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。它将会通过进行一系列曾经定义好的步骤疏导你:

参考资料

  • lerna github
退出移动版