平常的项目由于依赖包不多基本都是一个依赖使用一个仓库,但如果开发较为大型的项目,或者项目组件抽出的比较细,这种场景下一个依赖使用一个仓库就加大了管理难度。Monorepo
就是解决这样场景而产生的,像是Babel
、Vue3
、React
都是使用这样的管理方式。
Monorepo优劣势
优势
1、方便代码管理
依赖数据一旦多起来时,众多的项目仓库会使得修改关联功能需要在几个仓库间切换。
依赖分散,管理上需要更多的精力,如果缺乏持续性管理,可能导致功能模块定义偏差。或是各个项目内容易存在过多功能相同的代码,也不方便提取复用。
如果文档整理不全,有可能出现交接时导致仓库遗失的情况。
2、分支构建统一
由于模块数众多,各个模块的版本管理与模块分支对应也会越来越复杂。
由于模块数众多,可能因为某个小模块的代码修改而未被注意到,导致不容易检测。
3、方便复用与测试
所有依赖同在一个仓库,方便复用、修改、测试。
劣势
1、不利于权限管理
由于所有代码都放在同一个仓库,不利于做权限管理,对于项目不熟悉的人容易修改到其他地方代码。
2、仓库体积大
由于所有代码同放一个仓库,可能有时候修改一个小功能需要拉下完整的仓库。
如果是引入临时开发者或是新人,不利于快速上手项目。
Lerna、Yarn与Monorepo关系
文章标题提到Yarn
、Lerna
这是比较主流的Monorepo
仓库管理工具。
Yarn
是Facebook
为了解决NPM
使用中诸多问题而创立的包管理工具,其中自带了workspaces
功能,可以通过配置根目录的package.json
来实现Monorepo
仓库管理。但是Yarn
只解决了包管理的问题,对于包内的依赖、发版依然麻烦,此时就需要另一个工具Lerna
。
Lerna
就是Babel
项目在包管理时发现处理依赖等诸多不便,因此产生的管理工具。
Monorepo应用
安装
安装lerna
和yarn
npm i -g lerna yarn
初始化项目
进入目录,执行初始化命令
lerna init
lerna init --independent // 创建independent模式的项目
执行后在项目下会多出package.json
、lerna.json
文件和packages
目录。
packages
目录就是存放多个项目的目录,在配置文件中可以修改。
在package.json
可以添加一些配置,
"private": true, // 私有,主工程不会被发布
"workspaces": [ // 声明子package项目路径,yarn会读取使用
"packages/*"
]
lerna.json
可以配置一些参数:
- version: 版本号
- npmClient: 使用指定的包管理器,值为
yarn
、npm
。默认为npm
- command.publish.ignoreChanges: 值为数组,配置忽略变更的文件或目录
- command.publish.message: 自定义发布新版的提交信息,参看@lerna/version (翻译版@lerna/version)
- command.publish.registry: 配置发布的自定义仓库地址
- command.bootstrap.ignore: 值为数组,
lerna bootstrap
命令忽略的包 - command.bootstrap.npmClientArgs: 值为数组,
lerna bootstrap
命令时,会将此变量值传递给npm install
- command.bootstrap.scope: 值为数组,
lerna bootstrap
命令针对哪些包执行 - packages: 值为数组,所有子包的路径
依赖管理
安装依赖
只要在项目主目录下执行
yarn install
yarn
会自动读取workspace
配置,就能自动安装、处理、软链接各个子包的依赖,统一放在根目录下。
也可以使用lerna
的安装命令
lerna bootstrap
但可能不如yarn
的包管理机制好用,可以看这篇文章《Lerna的依赖管理及hoisting浅析》
增删依赖
主项目添加依赖
yarn add -W -D [packageName]
删除公共依赖
yarn remove -W -D [packageName]
给所有子项目增删依赖
yarn workspaces add [packageName]
yarn workspaces remove [packageName]
给某个项目增删依赖
yarn workspace [packageNameA] add [packageNameB] // packageNameA是指定安装依赖的包名,packageNameB是公共的包名或者项目内的包名
yarn workspace [packageName] remove [packageName]
当项目依赖凌乱的时候,可以使用命令清理依赖
lerna clean
其余还有一些命令
// 如果 package.json 中设置了 "private": true 的不会展示
lerna ls // 列出仓库中包信息
lerna changed // 查看项目变动
lerna exec // 执行命令
yarn workspaces info // 查看项目内信息
构建发布
使用lerna run
命令构建项目
lerna run build // 会执行子包中build命令构建
lerna
同时提供了快速版本发布功能
lerna version
执行后会自动识别修改的包,然后修改版本号。如果当前代码有未提交的修改记录则禁止更新。
使用带--conventional-commits
参数命令,可以支持Git的提交记录来自动更新版本号
lerna version --conventional-commits
详细的参数文档可以看@lerna/version或者@lerna/version翻译
之后可以用lerna publish
发布新包
lerna publish from-git // 显式发布在当前提交中标记的包
详细的参数文档可以看@lerna/publish或者@lerna/publish翻译