monorepo
monorepo(monolithic repository),与multirepo相对,分别是单代码仓库与多代码仓库(one-repository-per-module)
multirepo即传统做法,按模块分为多个代码库,实践中发现一些问题:
- issue管理混乱,经常有在core repo提module问题的,需要Close this and track that
- changelog难以整合,需要人工梳理所有变动的仓库,并做整合
- core repo版本更新麻烦,需要同步所有module更新其依赖的core repo版本
monorepo把所有相关module都放到一个repo里,每个module独立发布,但使用与该repo统一的版本号(例如Babel和React),issue和PR都集中到该repo,changelog可以简单地从一份commit列表梳理出来(甚至如果按照commit规范关联issue tag的话,能够自动生成规范的changelog)
monorepo也存在一些问题,但不如上面提到的痛点强烈:
- repo体积较大,可能带来版本控制的问题(Git不适合管理体积太大的repo)
- 统一构建工具,对构建工具提出了更高要求,要能构建各种相关module
从源码管理的角度来看,multirepo与monorepo是两种不同的理念,前者允许多元化发展,各个module可以有自己的玩法(构建,依赖管理,单元测试等),后者希望集中管理,减少玩法差异带来的沟通成本
monorepo标志性的特征是目录结构,例如React:
1 | react-16.2.0/ |
每个module都有自己的依赖项(package.json),能够作为独立的npm package发布,只是源码放在一起维护
创建lerna项目
1 | // 安装 |
得到如下结构:
1 | hoho-lerna/ |
创建一些模块
1 | mkdir packages/core && cd packages/module-a |
我们在module-a的package.json
中加入如下内容
1 | { |
这时使用lerna bootstrap
可以将每个库之间的依赖建立起来,你会发现module-a
中的node_modules
中有了core
(引用的方式)
lerna常用命令
run
Run an npm script in each package that contains that script
在每个包含此命令的package中运行此命令
1 | lerna run <script> -- [..args] # 在每个包含此命令的package中运行此命令 |
配置
指定范围
lerna run 接收三个标志来控制执行包的范围--concurrency
,--scope
,ignore
(更多请看这里)
--scope <glob>
只在给定的package中执行1
2
3lerna exec --scope my-component -- ls -la
lerna run --scope toolbar-* test
lerna run --scope package-1 --scope *-2 lint对于某些glob需要使用option的参数来避免shell过早执行
--ignore <glob>
1
2
3lerna exec --ignore package-{1,2,5} -- ls -la
lerna run --ignore package-1 test
lerna run --ignore package-@(1|2) --ignore package-3 lint--no-private
排除私有package,默认情况下是包含他们的
--npm-client <client>
指定执行命令的包管理工具,默认是npm
1 | lerna run build --npm-client=yarn |
也可以在lerna.json中这样设置
1 | { |
stream
将子进程的输出以流的形式输出,以原始包名称为前缀,这会让不同包交错输出。
1 | lerna run watch --stream |
--parallel
与–stream类似,但完全忽略并发和拓扑排序,在带有前缀流输出的所有匹配包中立即运行给定的命令或脚本。这是长时间运行进程的首选标志,例如运行在许多软件包上的npm run watch
。
1 | lerna run watch --parallel |
建议在使用–parallel标志时约束此命令的范围,因为产生数十个子进程可能对shell的平等(或最大文件描述符限制)有害
--no-bail
1 | lerna run --no-bail test |
默认情况下lerna run
遇到错误会退出,使用这个参数可以忽视错误
--no-prefix
输出为流时( - stream或–parallel),禁用包名称前缀。将结果传递给其他进程(如编辑器插件)时,此选项非常有用。
bootstrap
参考: