谈论从把多项目合并成一个项目中获得的收益

在开源社区流行着这样两种项目管理的方式:

  • 多repo仓库管理 (multirepos)
  • 单repo仓库但是多包管理 (monorepos)

在很早的时候, 我的项目 tailchat 是一个典型的多repo管理的项目。

我创建了一个组织,组织下有多个tailchat相关的项目:

  • tailchat
  • tailchat-server
  • tailchat-website
  • tailchat-cli
  • tailchat-rss-bot
  • tailchat-archive
  • tailchat-docs
  • tailchat-meeting

多repo的好处在于绝对的隔离,独立的发布机制,独立的仓库上下文(issues/prs)。但是我在长期的时候中逐步发现了多repo管理上的问题,以至于我抽出了时间将其合并成了一个项目。

接下来我会说说我遇到的问题。

多repo遇到的问题

精力上的分散

多repo意味着要同时管理多个项目,一些边缘的repo甚至会长久的失去维护。对于开源项目来说失去维护意味着死亡。而开源项目也往往会意味着管理人员精力上的分散,不论是企业支持的开源项目来说还是个人支持的开源项目来说。

比如react社区知名的UI组件库 antd。作为一个热门库来说它一直保留着非常高的活跃度,也不缺少维护人员。但是他的基础库rc-xxx却很少有人去处理pr。因为摊子铺的很大,十几个小的组件库分成不同的repo,就意味着开发组的成员很难分配精力在这些改动并不频繁的仓库上面。

发版与分发上的割裂

以最基本的前后端分库来看(client/server),两个repo意味着两套发版流程(当然可以说通过第三方平台把他们组合在一起,这个我们暂且不讨论)。同时意味着你不得不打两个tag,发两个release,以及跑两个CICD流程。如果你有一个website项目(文档)。你不适合放在任意一个client/server 仓库。这不得不造成你必须再创建第三个项目。

这三个项目从逻辑上来看确实是没有任何关系,但是在业务上来看却是耦合在一起的!这三者的同步就意味着需要花费维护者额外的精力,也意味着风险。

产物困难

另外就是项目的产物,多repo意味着多产物。多产物也意味着用户需要更多的上下文,对于不了解或者不愿意了解的用户来说这就是额外的错误可能以及精力成本。额外的入门门槛会极大的打击用户的使用信心。

一个简单的例子就是,作为用户更加希望只需要部署一个应用就能完成一切。而一个需要 前端+后端 的项目意味着额外的学习成本,不友好。

基本配置不通用

多repo的管理机制还有一个常见的问题就是项目的配置没有办法通用。比如 Tailchat 项目是使用 typescript 来进行开发的,还需要一些自动化工具比如代码格式化,代码检查,git hooks等。那么一个项目需要配套: tsconfig.json, commitlint, prettier, eslint, lintstage, editorconfig

多个项目就要配多套配置。如果改了一处需要把所有的项目都改一遍。想想就简直是一场噩梦!

当然可以产出一套工具专门管理相关的配置,但是这也意味着额外的精力成本,同时也引出了另一个问题,那就是改动的滞后性 —— 改动的配置没有办法立即产生效果,必须提交代码到这个工具的仓库 -> 发布 -> 同步到所有相关的仓库中。

如果说我们花了太多的时间在这种事情上,那我可以认为,这个项目的DX(Developer Experience) 是失败的。

贡献的积极性

另外一个比较隐晦的问题在于,对于开源项目来说,多个包往往也会打击潜在贡献者的贡献积极性,贡献者往往期望往主库去提交代码,而多库意味着贡献的分散化。

使用 monorepos 结构后我获得的收益

自从将原来的项目结构修改为monorepo以后,写代码都舒服了很多。其中立即能够获得的收益包括但不限于:

  • 依赖缓存复用
  • 一套配置所有项目受益
  • 统一管理所有 action 和 action env
  • 产物统一,只需要输出一个docker镜像
    • 用户也反馈部署更加方便了
  • 统一版本号,不会再出现前端一个版本后端一个版本的情况了
  • 打开项目更加方便了,不需要打开多个repo
  • 只需要关注一个项目的 github webhook 就可以订阅所有动态

同时,其他一些可能的操作也变得有可能了,比如:

  • 编写脚本,从客户端与服务端的代码中收集信息自动生成文档。
  • 客户端根据服务端代码自动生成网络请求代码

当然,有受益就有付出,monorepos 目前给我带来的问题有:

  • pnpm install的时间更长了,因为需要安装/编译的内容更多了
  • docker build的时间更长了,因为每次打包都需要同时编译前端和后端的项目,而不管有没有发生修改。
  • node_modules的内容过多导致在tree viewer中翻页会比较困难。

我觉得这些问题都是可以接受的,相比收益来说这点付出几乎可以说是忽略不计。当然这只能说是个人开发者或者小团队开发能够有很大收益的方式,对于大型团队来说,monorepos的方式会带来很高的沟通成本和管理成本。只能说存在即合理,作为开发人员我们需要找到适合自己的当前状况的最优解。

文章目录
  1. 1. 多repo遇到的问题
    1. 1.1. 精力上的分散
    2. 1.2. 发版与分发上的割裂
      1. 1.2.1. 产物困难
    3. 1.3. 基本配置不通用
    4. 1.4. 贡献的积极性
  2. 2. 使用 monorepos 结构后我获得的收益