monorepo的演化

假设:现有一个Web前端项目,需要同时支持微信公众号以及自己公司定制的App,需由你的小组开发完成。

演化阶段一

那么针对以上需求,很有可能将所有的代码放在一起。文件夹可能如下,并放置在一个仓库里:

.(git1)
├── shared
│   ├── wechat-sdk    # 微信SDK适配。如:支付、拍照等
│   └── app-sdk       # App-SDK适配。如:App的支付、拍照等
└── app

演化阶段二

假设:由于随着公司的发展,扩展了新的业务模块二,并且还是由你的项目小组开发完成。

那么针对以上需求,可能会将项目结构设计为:

.(git1)
├── shared
│   ├── utils         # 公用方法、样式等
│   ├── wechat-sdk    # 微信SDK适配。如:支付、拍照等
│   └── app-sdk       # App-SDK适配。如:App的支付、拍照等
└── app
    ├── module1    # 原业务:模块一
    └── module2    # 新业务:模块二

好像并没有什么区别,对吧?只是调整了项目的文件结构,继续往下看。

演化阶段三

假设:公司继续飞速发展,模块一、模块二也随之发生了急剧的扩张,你的小组成员已经没有精力同时完成2个模块,这时领导们说两个模块独立成为网页应用,并由不同小组共同维护。

那么针对以上需求,你开始犯难了,有太多的公用的东西,怎么可以保证SDK中的东西同时同步到两个项目组呢?那么经过一番思考~

小样这还难得到我,将原来的项目拆分成3个小项目:

  • git1-shared # 公共资源项目
  • git2-app1 # 原模块一
  • git3-app2 # 原模块二

两团队共同维护 git1-shared,分别维护 app1app2,那么项目以及git仓库结构如下:

.(git1-shared)        # 公共资源项目
└── shared
   ├── utils         # 公用方法、样式等
   ├── wechat-sdk    # 微信SDK适配。如:支付、拍照等
   └── app-sdk       # App-SDK适配。如:App的支付、拍照等
.(git2-app1)          # 原模块一
└── app
   ├── src           # 原module1源码
   └── dependency    # 项目依赖:原shared
.(git3-app2)          # 原模块二
└── app
   ├── src           # 原module2源码
   └── dependency    # 项目依赖:原shared

演化阶段四

假设:经过日积月累,你开始对产品经理烦躁起来。因为你发现,公用的内容 shared 稍微调整你就要不断的修改、测试、构建、发布。流程一步都不能少,信息还要在2个团队中同步。简直想抡起键盘砸向产品经理。

但是心想,产品不提需求你没饭吃啊,逐渐你放下手上的键盘,仔细思考起来。要是一个仓库能同时放多个项目该多好,这样即可以愉快的联调,也不需要频繁向其他团队同步信息。那么你设计出了以下结构:

.(git1)
├── shared            # 拥有独立结构的项目
│   ├── utils         # 公用方法、样式等
│   ├── wechat-sdk    # 微信SDK适配。如:支付、拍照等
│   └── app-sdk       # App-SDK适配。如:App的支付、拍照等
└── apps
     ├── app1         # 拥有独立结构的项目
     └── app2         # 拥有独立结构的项目

这样就同时兼顾了多项目管理、但是公用的资源又同时放在一个仓库中,可以同时修改、测试、构建、发布。大大减少了中间的流程。其实这最后一种就是monorepo管理形式了。

总结

上述演化过程中的阶段一阶段二MONOLITH; 阶段三MULI-REPO;阶段四MONO-REPO

各项目结构管理的优缺点

名称优点缺点
NonoLigth实现简单复杂项目代码复用性低,且不利于团队协作。
MultiRepo模块划分清晰,每个模块都是独立的 repo,利于团队协作代码管理难度增加。比如:
1.某个模块出现bug 相应模块都需要编译、上线、涉及到手动控制版本非常繁琐。
2.issue 管理十分麻烦。
MonoRepo代码结构清晰,利于团队协作,同时一个库降低了项目管理、代码管理以及代码调试难度。项目变得庞大,模块变多后同样会遇到各种问题。所以需要有更好的构建工具支持。

选择

可以根据不同的项目需求,对项目未来发展的合理预期来选择项目结构。不必要直接选择monorepo,也可以考虑选择我们最原始的慢慢迭代到monorepo,可以根据不同情况进行选择与演变。