源自Babel的多包管理工具:Lerna


编者按:本文做者:刘观宇,360 奇舞团高级前端工程师、技术经理,W3C CSS 工做组成员。前端

多包合做的烦恼

在开发须要多个密切协做的软件包时候,咱们每每将独立的功能块进行划分,使得各个功能独立的模块分别完成,以减小相互影响,完成有效的多人合做。可是,在模块协做时,常常会遇到一些问题:vue

  1. 依赖处理繁琐。node

  2. 依赖的模块,尚处在开发之中,通行的npm install、yarn等没法从安装源中得到。react

  3. 被依赖的模块版本升级,模块其余版本须要手动管理相关的版本。git

  4. 有循环依赖的风险github

对于多个模块的大型项目的协做管理,通常地有multirepo、monorepo和submodules等多种方式:multirepo是将多个模块分别分为多个仓库,早期的Babel(Babel6之前)使用的就是这种方式;submodules是借助git的实现,在.gitmodules中写明引用的仓库,在主仓库中只保留必要的索引;monorepo则是将相关的模块用单一的仓库统一管理。vue-cli

上述的方式各有优劣。从目前前端工程的代码管理来看,monorepo被不少超级repo选中。Babel、vue-cli、create-react-app都采用这种模式。npm

Babel的重要贡献者Jamie Kyle1,在为 Babel 6 工做的过程当中发现全部东西都拆分红漂亮的小插件包,但同时也就须要管理数十个软件包。所以,多包存储库管理工具 Lerna 应运而生。为让项目更好用,他对项目进行了屡次重写,试图让架构更完善。下图是Jamie Kyle的靓照@_@json

Lerna也是Babel官方如今使用的多包管理工具。bootstrap

什么是Lerna

Lerna官网2对此给出了官方的解释:Lerna是一个管理包含多个软件包的JavaScript项目的工具。它能够:

  1. 解决包之间的依赖关系。

  2. 经过git仓库检测改动,自动同步。

  3. 根据相关的git提交的commit,生成CHANGELOG。

Lerna是一个命令行工具,能够将其安装在系统全局。简单的命令说明,可使用:lerna -h查看命令帮助。

两种模式

Lerna分为两种模式:fixed模式和independent模式。两种模式的区别在于:前者强制全部的包都使用在根目录lerna.json中指定的版本号。然后者各个软件包,能够本身指定版本号。

默认的,lerna使用的是fixed模式。笔者认为,这种模式下,全部的相关软件包,最好以几乎一致的发布周期发布,如Babel这种。而且软件内部应该被使用者更多以“黑盒”方式对待。这是fixed模式最适应的方式。

而须要暴露内部包的细节,或者迭代频率显著不一致的包,建议采用independent模式。

指定为independent模式,能够在lerna init时加入--independent,或者将lerna.json的version字段指定为independent。

Lerna配置

lerna.json一般位于项目的根目录下,定义了lerna运行的主要行为。当在根目录下运行lerna initlerna init --independent时,会自动生成。如下是一个典型的配置:

{

  "version": "1.1.3",

  "npmClient": "npm",

  "command": {

    "publish": {

      "ignoreChanges": ["ignored-file", "*.md"],

      "message": "chore(release): publish"

    },

    "bootstrap": {

      "ignore": "component-*",

      "npmClientArgs": ["--no-package-lock"]

    }

  },

  "packages": ["packages/*"]

}

上面的配置文件中:

  1. version指定的是全部包的统一版本号;对于independent模式,这个字段请指定为independent;

  2. npmClient指定的是npm的客户端。默认的,lerna将使用npm。读者也可依所需将程序设置为yarn,甚至cnpm等等。

  3. command字段,能够对publish和bootstrap命令进行参数传递和命令定制。如:command.publish.ignoreChanges,用来设置一些忽略的文件,以免无关文件的提交对于版本号的变动,如README.md等等。command.bootstrap.npmClientArgs指定在bootstrap命令时,传递的默认参数,好比咱们会经常使用--no-package-lock来禁止package-lock.json或yarn.lock等等。

  4. packages字段指定包所在的目录。

Lerna命令

初始一个多包的工程

lerna init

上述命令会初始化一个多包工程。初始化以后会在根目录生成packages目录、lerna.json,若是使用independent模式,请使用命令:lerna init --independent

建立子包

lerna create <package> [-y]

在packages所指目录下建立package包。

添加包

lerna add <package>[@version] [--dev] [--exact] [--scope=module名]

上述命令会添加一个包package指明的软件包。

指定--dev是添加在devDependencies中。

指定--exact,则将用精确匹配的版本添加包。

指定--scope将只在此指明的模块中安装这个软件包,不然将在全部packages目录中的包中安装。

对于packages目录下的子包,将经过设立systemlink来解决依赖。

对于npm镜像中存在的包,将安装镜像中的包。

运行命令

运行命令分为两种:任意命令和npm scripts定义的命令。

对于任意命令使用,lerna exec;对于npm scripts定义的命令使用lerna run

lerna exec为例:

lerna exec [--concurrency number] [--stream] [--parallel] -- <command> [..args]此命令,在全部包中运行所指定的命令。

特别地,lerna exec -- rm -rf ./node_modules将删除全部包中的依赖。lerna exec -- npm uninstall <package>将移除全部的package依赖。

lerna execlerna run 如须要每一个子模块相继的执行并按顺序输出,能够指定--concurrency 1。

对于指定了--stream的命令,将把全部子进程的输出当即回显此举可能形成子进程显示顺序交叉,为了分辨输出来源,每一个输出,会带上包名;指定了--parallel的命令,则会在scope指定的范围内,并行地执行相关地命令。

lerna run与上述命令不同的状况在于,lerna run build将在每个包中scripts字段中执行定义的build命令。

安装全部依赖

lerna bootstrap

上述命令安装全部的依赖、将全部的相关连接作好,同时在全部的包中运行npm run prepublish。随后,在全部包中运行npm run prepare。此时,全部的依赖均已完备。

发布

lerna publish 发布全部的包。

清理

lerna clean 删除全部的node_modules

一些优化

合并公共依赖

咱们在开发过程当中,常常发现包依赖相似。这样,咱们发现运行lerna bootstrap以后,会重复安装依赖包,这样会形成空间的浪费和效率的下降。为此,咱们能够把一样的依赖包在根目录安装一次便可。此时,可使用lerna bootstrap --hoist命令,则公用的依赖,只会在顶层目录安装一次。

发布带有scope公有包

带有scope的包,须要发布时候,若是是公有的包,须要在npm publish时候使用npm publish --access public。为了可以成功publish,并使用lerna流程,请在每一个子包的package.json中加入:

"publishConfig": {

    "access": "public"

  }

检测循环依赖

lerna自己内置了检测循环依赖的功能,若是出现循环依赖。会在bootstrap时候给出提示:

此时,请依照提示去掉循环依赖,以保证软件包的正常运行。

文内连接

  1. https://github.com/jamiebuilds

  2. https://lerna.js.org/


若是你喜欢探讨技术,或者对本文有任何的意见或建议,很是欢迎加鱼头微信好友一块儿探讨,固然,鱼头也很是但愿能跟你一块儿聊生活,聊爱好,谈天说地。鱼头的微信号是:krisChans95 也能够扫码关注公众号,订阅更多精彩内容。


本文分享自微信公众号 - 鱼头的Web海洋(krissarea)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。

相关文章
相关标签/搜索