原文:github.com/lerna/lernagit
一个用于管理具备多个包的JavaScript项目的工具。github
将大型代码库拆分为单独的独立版本包对于代码共享很是有用。然而,跨多个存储库进行更改是混乱的,并且很难跟踪,跨存储库的测试也变得很是复杂。npm
为了解决这些(和许多其余)问题,一些项目将其代码库组织到多包存储库(有时称为monorepos)。像Babel、React、Angular、Ember、Meteor、Jest等项目在一个存储库中开发全部的包。json
Lerna是一个工具,它优化了使用git和npm管理多包存储库的工做流。bootstrap
Lerna还能够减小开发和构建环境中对包的大量副本的时间和空间需求,这一般是将项目划分为多个单独的NPM包的缺点。有关详细信息,请参阅 提高 提高文档。数组
事实上不多有。您的文件结构以下所示:服务器
my-lerna-repo/
package.json
packages/
package-1/
package.json
package-2/
package.json
复制代码
Lerna中的两个主要命令是Lerna bootstrap和Lerna publish。babel
bootstrap将把repo中的依赖项连接在一块儿。publish将帮助发布任何更新包。app
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)。
固定模式Lerna项目在一个版本行上运行。版本保存项目根目录下lerna.json文件,在version键下。运行lerna publish时,若是某个模块自上次发布以来已更新,则它将更新为您要发布的新版本。这意味着您只在须要时发布包的新版本。
注意:若是您的主版本为0,则全部更新都将被视为中断。所以,使用主版本零运行lerna publish并选择任何非预发布版本号将致使为全部包发布新版本,即便不是全部包自上次发布以来都发生了更改。
这是babel目前使用的模式。若是要自动将全部包版本绑定在一块儿,请使用此选项。这种方法的一个问题是,任何包中的重大更改都将致使全部包都有一个新的主版本。
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查看全部可用的命令和选项。
{
"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/*"]
}
复制代码
在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"
}
}
复制代码
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)。