# Monolith 和 MultiRepo 存在什么问题
# Monolith 单仓库巨石应用
用一个 git 仓库来维护项目代码,随着业务复杂度的上升,代码量会急剧上升,最终项目会变得十分庞大,复杂, 难以继续维护,更新迭代,并且构建效率也会降低。
- 存在的问题:
- 代码耦合度非常高,可能改了这里,又会影响那里,并且当我们排查问题时,难度也变得非常高,可能很多时间都花在了找代码上面。
- 代码量非常大,项目构建的效率低下,明明只改了一点点代码,却要重新构建整个代码,构建花费的时间非常长。
# MultiRepo 多仓库多模块应用
将一个项目拆解为多个多个模块,放在多个 git 仓库里面管理,直接的对项目进行了解耦,每个单独的模块都可以独立的编码,测试,发布。
- 存在的问题
- 各个仓库之间的代码共享非常困难,粗糙,一般想要进行代码的共享只有如下几种方式:
- 将需要共享的代码复制粘贴到自己的仓库里
这种方式会明显的造成代码体积变大,从而影响构建效率 - 将需要共享的代码单独维护成一个仓库,发布成 npm 包,
这样方式很麻烦,每次都需要,重新发布 npm 包,然后在使用了这些共享的代码的仓库里npm install
更新 npm 包。
并且当维护的 npm 包出现了break change
的时候,只有等到 npm 包发布,并且各个仓库更新了 npm 包的时候,才能发现问题,问题发现不及时,导致排查问题,解决问题,十分困难。 - 通过
npm link
来实现本地开发的时候共享代码,这种方式相比上面两种方式好了很多,但是依旧需要手动在需要共享代码的仓库里npm link
,在需要使用其他仓库共享的代码的仓库里npm link <package-name>
- 将需要共享的代码复制粘贴到自己的仓库里
- 版本管理很困难,当一个仓库有更新,需要发布的时候,需要在其他所有依赖这个仓库的仓库里执行
npm install
来使用这个刚更新仓库的最新版本。 - 无法积累一个统一的工程化配置,从而复用,每次有新的项目的时候都要重新配置一次几乎一摸一样的,
ci
,lint
,构建
,等流程
- 各个仓库之间的代码共享非常困难,粗糙,一般想要进行代码的共享只有如下几种方式:
# 采用 Monorepo 架构 可以解决这些问题吗?会有哪些好处
# 将 Monolith 巨石应用 换成 Monorepo 架构
- 将巨石应用,分为了不同的模块,在一定程度上进行了解耦,明显的降低了耦合性,既降低了维护成本(找代码,改代码),也降低了新人上手门槛。
- 当代码有更新,有变动的时候,只需要进行增量构建,只构建,发布,有变动的模块和使用了有变动的模块的模块,而不需要构建所有的代码,大大提升了构建效率。
# 将 MultiRepo 多仓库多模块应用 换成 Monorepo 架构
- 模块之间的代码共享,更加便捷,安全,问题发现更加及时。所有的模块都在一个仓库里,可以很轻松的使用维护的对外共享代码的模块共享的代码,并且当对外共享代码的模块出现问题时,在开发阶段就可以及时发现,解决,而不是像
MultiRepo
一样,只能等到 npm 包发布,才能发现。 - 现代的众多
monorepo
工具可以实现自动的版本管理,当有模块更新的时候,自动更新该模块,和使用了该模块的模块。 - 可以积累下统一的工程化配置,多模块共同使用,当有新的项目的时候,可以作为一个新的模块直接接入,不再需要进行重复的工程化配置。
- 所有的项目,公共函数库,公共组件库,都作为一个模块在一个仓库里,作为数据资产落地下来,便于新人快速上手,知晓有哪些公共函数,公共组件,可以使用,并维护,提升开发效率。
# 直接无脑的使用 Monorepo 架构,会带来哪些问题呢,可以解决吗?
# 可能带来的问题
- 所有的项目都作为模块在同一个仓库里,可能出现改了其他模块的代码,并且负责该模块的同事还不知道,结果出现了问题。
- 在维护对外共享代码的模块(比如,组件库,函数库, hooks 库)的时候,无意间造成了
break change
,从而影响了其他使用了该模块的模块的正常运转。 - 在更新对外共享代码的模块的时候,不通知更新内容,从而使其他同事不知道公共模块多了哪些东西,导致对外共享模块形同虚设,无法发挥作用。
# 解决方案
团队需要有严格的 commit msg
规范,每次的 commit msg
必须附上,更改的模块名;当公共模块有更新的时候,必须写上更新内容,并告知团队成员,一方面当不小心造成 break change
时,团队成员能够及时发现,并解决。另一方面,团队成员可以及时知道公共模块更新了哪些内容,自己是否可以用到,从而放公共模块发挥作用。
团队需要有严格的 code review
作为兜底
# 总结
Monorepo 架构确实拥有着很大的优势(解耦;增量构建,提升构建效率;代码共享;积累统一的工程化配置,公共库,从而提高开发效率,积累数据资产;降低新人上手门槛),可以带来很多积极的作用,但是对团队规范有一定的要求,无脑的使用,可能会带来很多致命的问题,但是可以通过严格的团队规范来避免。