lerna+yarnworkspace+monorepo项⽬的最佳实践
对于维护过多个package(功能相近)的同学来说,都会遇到⼀个选择题,这些package是放在⼀个仓库⾥维护还是放在多个仓库⾥单独维护。Multirepo 是⽐较传统的做法,即每⼀个 package 都单独⽤⼀个仓库来进⾏管理。Monorepo 是管理项⽬代码的⼀个⽅式,指在⼀个项⽬仓库 (repo) 中管理多个模块/包 (package),不同于常见的每个模块建⼀个 repo。
⽬前有不少⼤型开源项⽬采⽤了这种⽅式,如 Babel,React, Meteor, Ember, Angular,Jest, Umijs, Vue, 还有 create-react-app, react-router 等。⼏乎我们熟知的仓库,都⽆⼀例外的采⽤了monorepo 的⽅式,可以看到这些项⽬的第⼀级⽬录的内容以脚⼿架为主,主要内容都在 packages⽬录中、分多个 package 进⾏管理。
⽬录结构如下:
├── packages
|├── pkg1
||├── package.json
|├── pkg2
||├── package.json
├── package.json
monorepo 最主要的好处是统⼀的⼯作流和Code Sharing。⽐如我想看⼀个 pacakge 的代码、了解某段逻辑,不需要它的 repo,直接就在当前 repo;当某个需求要修改多个 pacakge 时,不需要分别到各⾃的 repo 进⾏修改、测试、发版或者 npm link,直接在当前repo 修改,统⼀测试、统⼀发版。只要搭建⼀套脚⼿架,就能管理(构建、测试、发布)多个 package。
⼀图胜千⾔:
当然到底哪⼀种管理⽅式更好,仁者见仁,智者见智。前者允许多元化发展(各项⽬可以有⾃⼰的构建⼯具、依赖管理策略、单元测试⽅法),后者希望集中管理,减少项⽬间的差异带来的沟通成本。
虽然拆分⼦仓库、拆分⼦ npm 包是进⾏项⽬隔离的天然⽅案,但当仓库内容出现关联时,没有任何⼀种调试⽅式⽐源码放在⼀起更⾼效。
结合shop-service门户的实际场景和业务需要,天然的 MonoRepo ! ⼀个理想的开发环境可以抽象成这样:“只关⼼业务代码,可以直接跨业务复⽤⽽不关⼼复⽤⽅式,调试时所有代码都在源码中。”
在前端开发环境中,多 Git Repo,多 npm 则是这个理想的阻⼒,它们导致复⽤要关⼼版本号,调试需要 npm link。⽽这些是MonoRepo 最⼤的优势。
上图中提到的利⽤相关⼯具就是今天的主⾓ Lerna ! Lerna是业界知名度最⾼的 Monorepo 管理⼯具,功能完整。
2. Lerna
Lerna 是⼀个管理多个 npm 模块的⼯具,是 Babel ⾃⼰⽤来维护⾃⼰的 Monorepo 并开源出的⼀个项⽬。优化维护多包的⼯作流,解决多个包互相依赖,且发布需要⼿动维护多个包的问题。
2.1 安装
推荐全局安装,因为会经常⽤到 lerna 命令
npm i -g lerna
2.2 初始化项⽬
lerna init
其中 package.json & lerna.json 如下:
// package.json
{
"name": "root",
"private": true, // 私有的,不会被发布,是管理整个项⽬,与要发布到npm的解耦  "devDependencies": {
"lerna": "^3.15.0"
}
}
// lerna.json
{
"packages": [
"packages/*"
],
"version": "0.0.0"
}
2.3 创建npm包
增加两个 packages
lerna create @mo-demo/cli
lerna create @mo-demo/cli-shared-utils
2.4 增加模块依赖
分别给相应的 package 增加依赖模块
angular安装lerna add chalk // 为所有 package 增加 chalk 模块
lerna add semver --scope @mo-demo/cli-shared-utils // 为 @mo-demo/cli-shared-utils 增加 semver 模块lerna add @mo-demo/cli-shared-utils --scope @mo-demo/cli // 增加内部模块之间的依赖
2.5 发布
lerna publish
2.6 依赖包管理
上述1-5步已经包含了 Lerna 整个⽣命周期的过程了,但当我们维护这个项⽬时,新拉下来仓库的代码后,需要为各个 package 安装依赖包。
我们在第4步 lerna add 时也发现了,为某个 package 安装的包被放到了这个 package ⽬录下的 node_modules ⽬录下。这样对于多个package 都依赖的包,会被多个 package 安装多次,并且每个 package 下都维护 node_modules ,也不清爽。于是我们使⽤ --hoist 来把每个 package 下的依赖包都提升到⼯程根⽬录,来降低安装以及管理的成本。
lerna bootstrap --hoist
为了省去每次都输⼊ --hoist 参数的⿇烦,可以在 lerna.json 配置:
{
"packages": [
"packages/*"
],
"command": {
"bootstrap": {
"hoist": true
}
},
"version": "0.0.1-alpha.0"
}
配置好后,对于之前依赖包已经被安装到各个 package 下的情况,我们只需要清理⼀下安装的依赖即可:lerna clean

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。