Lerna(翻译)

2,593 阅读6分钟

原文:github.com/lerna/lerna

一个用于管理具有多个包的JavaScript项目的工具。

关于

将大型代码库拆分为单独的独立版本包对于代码共享非常有用。然而,跨多个存储库进行更改是混乱的,而且很难跟踪,跨存储库的测试也变得非常复杂。

为了解决这些(和许多其他)问题,一些项目将其代码库组织到多包存储库(有时称为monorepos)。像Babel、React、Angular、Ember、Meteor、Jest等项目在一个存储库中开发所有的包。

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

Lerna还可以减少开发和构建环境中对包的大量副本的时间和空间需求,这通常是将项目划分为多个单独的NPM包的缺点。有关详细信息,请参阅 提升 提升文档。

Lerna repo是什么样子的?

事实上很少有。您的文件结构如下所示:

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

Lerna能做什么?

Lerna中的两个主要命令是Lerna bootstrap和Lerna publish。

bootstrap将把repo中的依赖项链接在一起。publish将帮助发布任何更新包。

Lerna 不能做什么?

Lerna不是无服务器monorepos的部署工具。提升可能与传统的无服务器monorepo部署技术不兼容。

开始使用

下面的说明适用于Lerna 3.x。我们建议在新的Lerna项目中使用它而不是2.x。

让我们从安装Lerna作为npm项目的开发依赖项开始。

$ mkdir lerna-repo && cd $_
$ npx lerna init

这将创建一个lerna.json配置文件以及packages 文件夹,因此您的文件夹现在应该如下所示:

lerna-repo/
  packages/
  package.json
  lerna.json

工作原理

Lerna允许您使用两种模式之一管理项目:固定模式或独立模式(Fixed or Independent)。

固定/锁定(Fixed/Locked)模式(默认)

固定模式Lerna项目在一个版本行上运行。版本保存项目根目录下lerna.json文件,在version键下。运行lerna publish时,如果某个模块自上次发布以来已更新,则它将更新为您要发布的新版本。这意味着您只在需要时发布包的新版本。

注意:如果您的主版本为0,则所有更新都将被视为中断。因此,使用主版本零运行lerna publish并选择任何非预发布版本号将导致为所有包发布新版本,即使不是所有包自上次发布以来都发生了更改。

这是babel目前使用的模式。如果要自动将所有包版本绑定在一起,请使用此选项。这种方法的一个问题是,任何包中的重大更改都将导致所有包都有一个新的主版本。

独立(Independent) 模式

lerna init --independent

独立模式Lerna项目允许维护人员独立地增加包版本。每次发布时,对于每个已更改的包,都将得到一个提示,以指定它是修补程序、次要更改、主要更改还是自定义更改。

独立模式允许您更具体地更新每个包的版本,并对一组组件有意义。将这种模式与语义释放之类的东西结合在一起,会让它不那么痛苦。(atlassian/lerna semantic release已经对此进行了研究)。

设置version: independent 键lerna.json以独立模式运行。

故障排除

如果您在使用Lerna时遇到任何问题,请查看我们的故障排除文档,您可以从中找到问题的答案。

常见问题解答

FAQ.md.

概念

当它在运行命令时遇到错误Lerna会记录到lerna-debug.log文件(与npm-debug.log相同)。

Lerna还支持作用域包

运行lerna--help查看所有可用的命令和选项。

lerna.json

{
  "version": "1.1.3",
  "npmClient": "npm",
  "command": {
    "publish": {
      "ignoreChanges": ["ignored-file", "*.md"],
      "message": "chore(release): publish",
      "registry": "https://npm.pkg.github.com"
    },
    "bootstrap": {
      "ignore": "component-*",
      "npmClientArgs": ["--no-package-lock"]
    }
  },
  "packages": ["packages/*"]
}
  • version: 存储库的当前版本
  • npmClient: 用于指定运行命令的特定客户端的选项(也可以按每个命令指定)。更改为“yarn”以使用yarn运行所有命令。默认为“npm”。
  • command.publish.ignoreChanges: lerna changed/publish中不包含的globs。使用此选项可防止发布不必要的新版本进行更改,例如修复自README.md
  • command.publish.message:为发布执行版本更新时的自定义提交消息。有关详细信息,请参见@lerna/version
  • command.publish.registry: 使用它可以设置要发布到的自定义注册表url,而不是npmjs.org网站,如果需要,您必须已经通过身份验证。
  • command.bootstrap.ignore:运行lerna bootstrap命令时不会引导的globs数组。
  • command.bootstrap.npmClientArgs:在执行lerna bootstrap命令期间将作为参数直接传递给npm install的字符串数组。
  • command.bootstrap.scope:一个globs数组,用于限制在运行lerna bootstrap命令时将引导哪些包。
  • packages:要用作包位置的全局数组。

在lerna.json中的packages是一个文件数组匹配包含package.json的目录,这就是lerna如何识别“leaf”包(相对于“root”package.json,用于管理整个repo的dev依赖项和脚本)。

默认情况下,lerna将包列表初始化为[“packages/*”],但您也可以使用其他目录,如[“modules/*”]或[“package1”,“package2”]。定义的glob目录位置是相对于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/*下定位leaf包被认为是“最佳实践”,但不是使用Lerna的要求。

旧字段

一些lerna.json字段不再使用。值得注意的包括:

lerna:最初用来表示lerna的当前版本。使过时并在v3中删除

公共开发依赖性

大多devDependencies 可以通过Lerna link convert被拉到Lerna repo的根目录

上面的命令将自动提升对象并使用相对file: 说明符。

提升有几个好处:

  • 所有包都使用给定依赖项的同一版本

  • 可以使用诸如GreenKeeper这样的自动化工具在根目录上保持最新的依赖关系

  • 减少依赖项安装时间

  • 所需存储更少

注意,提供npm脚本使用的“二进制”可执行文件的devDependencies 仍然需要直接安装在使用它们的每个包中。

例如,在这种情况下,要使lerna run nsp(和npm run nsp在包的目录中)正常工作,nsp依赖关系是必需的:

{
  "scripts": {
    "nsp": "nsp"
  },
  "devDependencies": {
    "nsp": "^2.3.3"
  }
}

Git托管的依赖项

Lerna允许将本地依赖包的目标版本写入git远程url,并使用commitish(git 版本标识)(例如,#v1.0.0或#semver:^1.0.0),而不是普通的数字版本范围。当包必须是私有的并且不需要私有的npm注册时,这允许通过git存储库分发包。

请注意,lerna并没有实际将git历史分割到单独的只读存储库中。【解决方案:从monorepo中实现“git-only”分发有多种方式供以后参考。1:splitsh 2:regular git filter-branch --subdirectory-filter packages/】这是用户的责任。(有关实施细节,请参阅此注释

// 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"
}

在上面的例子中,

  • llerna bootstrap将正确地将pkg-2符号链接到pkg-1。

  • 当pkg-2发生变化时,lerna publish将更新pkg-1中的commitish(#v1.0.0)。