Monorepo在前端工程里为什么越来越重要?

520 阅读7分钟

日益复杂的前端工程,部分业务和工具库、CI、config等通常设计到多个仓库,久而久之,多个仓库的弊端就会显露出来,由此而诞生了一种新的软件管理方式--Monorepo,本文将详细介绍Monorepo的概念、收益和落地以及MultiRepo的弊端等来认识和学习下Monorepo,欢迎大家 踊跃讨论。

一、什么是Monorepo?

在软件工程,是指将多个项目或者工具库放在同一个代码仓库里面统一进行管理的一种软件管理的模式。

15825758-e228917fd3a382bc.webp

二、有谁在用?

yarn、react-router、Vue3、npm7、babel、create-react-app、webpack/webpack-cli等很多都在使用

三、Monorepo目录结构

├── packages
|   ├── pkg1
|   |   ├── package.json
|   ├── pkg2
|   |   ├── package.json
|   ├── ...
|   ├── pkgn
|   |   ├── package.json
├── package.json
├── ...config

那么Monorepo到底有什么优势,能够让很多开发者推崇,并且落地这么广泛呢 ?

四、MultiRepo痛点

要想知道Monorepo的优势,那么首先了解下传统的开发模式有什么劣势和不足之处。

(1)什么是MultiRepo?

对比于Monorepo而言,MultiRepo是指每个项目都单独对应一个代码仓库。

(2)MultiRepo之痛?

1.代码复用
  
  在维护和迭代开发项目的时候,有一些UI库、工具函数库,配置库,甚至一些CI流程会在每个项目里面都用到,那么我们传统的
  方案是CV大法,但是问题来了,如果这些代码或者配置出bug需要进行修复就需要修改多套,维护起来成本非常大,那么如何解决
  此类问题呢?比较传统的方式有提取公共代码发布npm包,那么只需要改一次然后publish到npm上即可,但是这个是完美的解决
  方案吗?显然不是那么如果你要修改某个逻辑首选需要做到以下几点
  
      (1)修改出现问题的组件库
      (2)对该库进行升级为新的版本的组件库
      (3)在用到的项目中安装新版本的组件库
      
  痛点就在于我修改了一个小的bug但是居然需要这么多流程,而我们在开发的时候,肯定避免不了bug出现,如果又发现了一个bug,
  那么还需要重复以上的流程,这个就是那么这个问题困扰开发者的痛点之一,那么能否优化呢?答案是肯定可以优化的,因为本文
  Monorepo就是来解决MultiRepo痛点的
  
2.版本管理
    
    在MultiRepo管理项目中,依赖包的版本管理是一个特别佛系的问题,比如多个项目依赖某个组件库,那么我们给该库
    update version的时候,和原来版本的api不兼容,也没有升级此依赖,会throw一些吗莫名的Error出来
    还有就是某些地狱依赖问题,(具体什么是地狱依赖,此文不多解释)
    那么上面的上述问题又是MultiRepo痛点之一

3.项目基建
    在MultiRepo项目中,各个项目的工作流是分裂的,所以每次都需要单独配置其环境,CI/CD流程等构建流程,甚至我们每个项目
    都有一套完整的脚手架或者配置流程等
    那么对于上面的诸多流程,都是重复的,对于重复的流程,我们前端工程最擅长维护了。
    还有就是在MultiRepo项目中,每个项目的规范等配置都是分裂的,没有进行统一管理,则会出现代码规范分裂的情况
    
3.依赖安装

    对于我们每个项目中,依赖都要重新到各个项目中安装,那么对于这个问题,相同版本的依赖,我只需安装一次,然后就可以使用到项目中去统一管理。
    

四、Monorepo的收益和优势

说完上述MultiRepo痛点,我们也很清楚的知道了上述的痛点就应该是Monorepo给我们带来的收益了,也应该知道为什么要出现
Monorepo这门软件管理方式去管理我们的代码了。

(1)首先呢就是正对MultiRepo痛点之一代码复用

  对于所有的UI库、工具函数库,配置库都在同一个代码库中,我们只需要修改一套代码即可,就可以简化发布npm包繁琐的
  流程,因为Monorepo可以实现本地包link的功能,修改完即可测试,不用publish和update
  

(2)工作流的一致性和完整性使得项目基建的成本降低

  因为代码库复用同一套标准的代码规范和基建流,比如CI/CD流,构建和发布等,这样就架构师维护即可,降低了维护成本
  

(3)有助于团队协作

  因为大家都在同一个代码库中开发,方便共享和复用,代码规范统一,另外,commit history也支持以功能为单位提交,简化
  commit记录,方便协作
  

(4)支持历史项目迅速加入代码仓库

  对于历史项目,我们可以直接import到我们新的代码仓库作为子模块去使用,并且可以import commit history record进来

(5)扩展性强,可维护性强

五、Monorepo的落地

如果您还没有接触过Monorepo的开发或者没听说过Monorepo的工程,此时你可能知道了,不就是吧所有的代码放到同一个仓库即可,
那么如果你这么认为那就大错特错了~

那么在实际的项目里面,Monorepo由一套完整的工程体系开支撑我们开发,所以不是简单的讲所有的代码堆放在同一个代码仓库
即可,需要进行各个子模块的依赖分析,依赖安装和提取,构建、测试、发布等一些列完整的流程,同时还要考虑项目达到一定程度
后的性能问题等,比如各种构建、测试,执行CI/CD的时间等都要考虑,所以我们在实现全面工程化优点能力的同时,千万不能忘记
我们前端中最重要也是最头疼的问题之一性能问题~

因此,想要从零到一来定制一套完整的Monorepo工程体系,绝非一件容易的事儿,因为需要做的事情太多太多了,不过丰富并且强大的前端生态已经为我们解决了上述的问题,并且提供了几套比较成熟的Monorepo方案,我们可以直接拿来定制使用

(1)Monorepo方案一【Lerna】

封装了Monorepo中的流程并且提供了一套完整的脚本执行命令,并且扩展能力很强,可以扩展包括update、test,release,
build,publish等流程,笔者也比较推荐使用Lerna去管理我们的前端项目

(2)Monorepo方案二【NX】

提供了一整套的流程,可以直接使用现成的架构体系,官网介绍的也很全面,还有视频教程,可供初学者去使用

(3)Monorepo方案二【rushstack】

也是提供了完整的工程体系能力,可以用来开发业务项目,但是缺点是如果想扩展来定制和维护几乎是行不通的

六、小结

最后,总之一句话,Monorepo开发模式就是MultiRepo的痛点将独立的代码放库放在同一个代码仓库使之成一个可执行的,可维护的
完整的架构体系,,提高开发效率和降低维护成本

问题一:解决了MultiRepo痛点,会不会产生新的问题呢?如果有,那么我们该怎么解决呢 ?
问题二:对于Monorepo而言,我们前端也有微服务,称之为微前端服务,那么有了微前端服务,Monorepo会不会被取代?
问题三:各位同行可有问题提出来我们共同探讨