浅尝 Monorepo

最初听说 Monorepo,是群里的同学问我是否了解 lerna,我还真没听说过,于是去学习了一下。简单来说,就是把好多个软件放在一个大型仓库里一起管理。

0. Monorepo 简介

为方便灵活使用,我们一般会把软件包拆散,每个小包只负责某个特定功能,通过组合完成复杂功能。这个时候我们有两个选择:

  1. 每个包放在独立仓库,独立管理、独立发布,然后通过 NPM 等包管理工具安装互为依赖。
  2. 所有包放在一起,统一管理,直接内部引用。即 Monorepo。

我之前在 OpenResty 一直使用前者,而很多开源项目都选择后者,比如 vue-cli。它的仓库里包含了 vue-cli 主体和大量插件,还有测试套件等。

这样做有几个显而易见的好处:

  1. 这些软件包通常高度耦合,彼此之间功能关联紧密。A 软件 X 版本依赖 B 软件的 Y 版本,B 软件的 Y 版本又依赖 C 软件的 Z 版本。统一管理切换环境更轻松。
  2. 统一管理依赖,既能减少磁盘占用,也可以保证开发环境统一。
  3. 没有编译、没有黑盒,所有源代码对项目成员公开,遇到问题分析调试都容易很多。

我觉得在 Google 这样的技术流公司这么搞没问题;在崇尚奉献和高参与质量的开源项目里这么搞也很好,但是对很多技术水平一般,自我要求很低的软件公司这么搞就是乱来了。

1. 问题

以我曾经短暂工作过的XX办公(为保护当事人隐私我隐去了“金山”二字)为例,使用 monorepo 带来了几个未曾预料的问题:

1.1 版本管理混乱

所有产品代码都放在一个仓库里,数个不同的团队同时进行开发,每天会产生大量的 commit。负责合并分支的人既不懂业务也不懂版本管理,基本就是点一下合并按钮,于是大量未经 rebase squash 的 commit 被用 merged 方式合并入主干。整个提交历史混乱不堪毫无价值。

同时由于采取 merge 方式,仓库里存在大量分支,git 无法判断版本之间的先后关系,也无法自动解决冲突,于是几乎每两三天就遇到冲突无法合并,需要开发人员解决冲突。

1.2 代码质量参差不齐,且互相影响

monorepo 好的一方面是代码对大家公开,所有人都可以学习其他人的写法,互相帮助解决问题;坏的一方面是坏的代码影响的也是整个项目仓库。

有些同学用 VS Code,这本身不是问题,但 ta 们不研究配置、不研究插件,于是代码中很多低级错误——甚至因为低级错误太多,反而不会报错。比如有个事件侦听函数,参数传进来是 e,但是函数体里用的是 event。结果竟然没有报错,也能通过测试(人肉)。我找到开发人员让他改,他发现竟然有一个全局 event 变量,不知道是谁在哪里带进去的……

【2022-09-20 更新】这里还真触及到我的知识盲区。这是早期 JS 的兼容性设计,即事件触发时 window 上也会有个全局变量 event,主要方便大家乱来。没想到救了 XX 办公。

1.3 技术栈升级困难

架构升级我就不谈了,这东西见仁见智,也不是能经常干的事情。这里说的主要是工具链。

如,eslint、错字检查、安全性检查。好比说,我发现部分代码存在风格问题,希望引入 eslint 检查,并且把 eslint 加入到集成环境里。按说这个想法并不复杂,这些工具都不影响整体架构,只需要外挂到 pre-commit 之类的钩子上即可。但此时必须征得整个开发团队几百号人的同意,那就不是一句话能解决的。

于是打开 WebStorm,海量的臭气(smell)扑面而来,难以直视。

1.4 代码互相耦合

原本 monorepo 只是方便大家阅读代码、维护代码。但是难免会有人滥用,直接引用、导入别人的代码,或者把自己的代码写入别人的目录里。

比如我想优化构建过程,希望能拆成 ES6 和 ES5 两个版本(因为厂里明确要求支持 ES5 的只有文档、表格、幻灯片)。然后我发现,虽然名义上大家各自维护自己的目录,但实际上跨目录引用比比皆是。简单按照目录区分基本不可能。

2. 总结

当然,我数落这些问题,不是想说 monorepo 不好。分散项目独立管理也会有别的问题,比如技术栈不统一、集成困难、人员变更后难以交接继承等。每种技术都会有适合的场景,各位技术决策者也应该从自己的团队实际出发,选择最适合自己的技术选型。

现在技术领域各种声音分外吵杂,很多公司会把技术方案作为一种宣传方式,名为推广技术实践,实则宣传自己的团队和品牌。如果不加区分盲目追随,就很容易掉进坑里。


如果你有使用 monorepo 的先进经验和最佳实践,欢迎分享给我。有其它想法和问题,也欢迎随时交流。

如果您觉得文章内容对您有用,不妨支持我创作更多有价值的分享:


已发布

分类

,

来自

标签:

评论

欢迎吐槽,共同进步

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据