袋鼠云数栈前端从 Multirepo 到 Monorepo 研发效率提升探索之路
我们是袋鼠云数栈 UED 团队,致力于打造优秀的一站式数据中台产品。我们始终保持工匠精神,探索前端道路,为社区积累并传播经验价值。
本文作者:星野
困境频生前端代码管理何解?
前端代码管理一直是困扰着不少前端开发团队的难题,从开发到发布的整体工作流程中,除了常规的技术问题外,往往还伴随着沟通成本、维护成本及协作效率等问题。这些问题在团队规模较小的时候可能不太明显,但是当团队规模变大时矛盾就越发凸显。
数栈前端开发团队负责着离线开发、实时开发、数据服务、数据资产等多条产品线的开发和维护工作,面对众多的产品线,如何合理的管理代码,成了团队需要思考的问题,虽然借助了 Multirepo 进行管理,但还是遇到了许多难题:
- 私有源维护成本增加
为复用相关业务逻辑,团队内部抽象出一些私有包,由于不能在公网暴露,为了管理这些私有包团队使用了私有源,但由于搭建私有源服务器资源问题,私有源常常不稳定且下载速度慢,特别是对于需要源码交付的某些客户来说,安装这些私有包更会遇到各种问题,交付的时间和人力成本大大升高。
- 逻辑难复用,重复造轮子
各个仓库中会抽象出同一功能的组件,组件之间的共享往往难以同步,造成了「重复造轮子」现象。
- 工具/配置不统一,沟通成本高
各个仓库所使用的工具和配置没有进行统一,在进行配置更新的过程中,往往需要同步到各个产品线负责人,沟通成本较高。
这些问题严重拖慢了数栈前端团队从开发到发布的整体流程,同时增加了团队的维护成本和沟通成本,如何寻找新的工具解决这些问题已迫在眉睫,在进行了深入调研和多次讨论的过程中,新的项目管理方式 Monorepo 在这时映入了我们的眼帘。
Multirepo VS Monorepo
那么 Multirepo 和 Monorepo 到底是什么呢?其实他们分别代表的是两种前端代码管理方式:
- Multirepo
Multirepo 是一种分散式的前端代码管理方式,按照功能或其他维度,将项目拆分为不同模块并单独维护于各自仓库中。作为传统的管理方式,Multirepo 具备灵活度高、安全控制等特点,但同时也带了管理成本和写作成本的增加,依赖升级等问题。
- Monorepo
Monorepo 是集中式管理的前端代码管理方式,将所有的项目在集中一个代码仓库中进行管理,严格的统一和收归,有利于统一的升级和管理。作为新型的管理方式,Monorepo 有效降低了运营及协作成本,但「一个代码仓库」的管理模式带来了项目体积的上升,获取时间延长,同时安全性也有所下降。

上图为 Multirepo 和 Monorepo 的对比图,从图中我们可以简要归纳:
- Multirepo 由多个仓库组成的项目管理方式,每个仓库有着独立的工作流、组件与配置。
- Monorepo 将不同仓库整合成为一个仓库,并共享工作流、组件与配置。
两种管理方式各有千秋,不能简单的定义哪种方式更好,但 Monorepo 的共享机制、统一管理及协作成本低等优势,显然更符合深陷复杂产品线挑战的数栈前端团队的需求,选择 Monorepo 也是团队探索效率提升的必然道路。
合适才最好 Monorepo 方案规划
确定了新的管理方式后,接下来面对的就是如何与数栈相适配的问题。市面上关于Monorepo的解决方案和相关工具有很多,虽然 rush、nx 之类的工具能够在特定的领域提供较好的解决方案,但却并不符合我们的实际需求。
在调研了社区的各种 Monorepo 实现和解决方案之后,结合我们自身的业务场景和需求,最终我们选择了 pnpm 和 turborepo 作为底层的包管理工具和任务调度工具,因为只有最合适的产品才是最好的解决方案。
- 包管理工具-pnpm
在前端社区中,npm、 yarn、 pnpm 三个包管理工具三足鼎立,而我们最终选择了 pnpm 原因在于:pnpm 对 monorepo 有着较好的支持,同时对比其他两个包管理工具,pnpm 在性能等各个方面有着显著的优势

- 任务调度工具-turborepo
任务调度方面,社区中也存在很多优秀的工具,如 rush、nx、lerna、turborepo等,综合对比之后,我们选择了配置简单易懂、调度更加科学的 turborepo 作为我们的任务调度工具:

不断探索 Monorepo 落地实践
在确定了底层包管理工具和任务调度工具后,数栈&Monorepo 整体架构方案也明确了:

Monorepo 解决了之前使用 Multirepo 时存在的问题,帮助我们更好的管理代码,接下来我们将结合 Multirepo 存在的问题来详细说明 Monorepo 是如何在数栈产品中落地的。
- 统一配置
Multirepo 存在的一个显著问题是配置的不统一导致的难以维护,所以我们需要对格式化、代码检测、打包等相关流程的配置进行规范化和统一,同时针对不同产品线的细微差别,也需要支持其灵活的扩展。因此我们在 Monorepo 仓库的根目录提供了统一的基础配置,同时如需要进行调整,不同产品线可以继承该配置并进行必要的修改。
- 逻辑复用
Multirepo 存在的另一个显著问题就是逻辑难以复用,迁移之前的逻辑复用主要是靠抽象到私有包并发布,或者直接复制粘贴,整体效率低,流程长且难以维护。迁移之后我们对各种配置等进行了统一的同时,也将公用的业务逻辑和组件整合到了仓库根目录的packages目录下,同时通过 pnpm 的 workspace protocal 链接到各个产品线中以便复用。这样不仅解决了逻辑复用的相关问题,同时私有源也不用进行维护,Multirepo 下的私有源维护成本问题得以解决。
- 权限校验
当基础配置和公共逻辑被暴露出来之后,就面临着这些内容可以被随意修改的问题,而这往往会影响所有的产品线,稍有不慎会造成巨大损失,因此我们需要给这些重要的内容施以限制和保护。
我们基于 git hooks 做了一些工作,在 pre-commit 和 pre-push 阶段分别对权限和分支名等内容进行了校验,并定义了 Maintainer、Owner、Deverloper 三个角色,对应的权限分别为:
- **Maintainer: **拥有全部权限,可以修改包括基础配置文件等的所有内容。
- Owner: 各产品线或者公共组件主要负责人,拥有对应范围内的所有权限。
- **Developer: **该产品线或者公共组件的辅助开发人员,只拥有包括开发新功能等的部分产品线权限。
角色权限进行明确的划分之后,我们可以将基础配置和公共逻辑等内容的修改交给更有经验的工程师。同时权限分配配置维护在本地,这样可以更清晰的了解不同产品线对应的人员,方便沟通。
- 自动化迁移
从 Multirepo 迁移到 Monorepo 如果采用手动的方式逐个迁移会有如下问题:
1.迁移前的各产品线仓库存在多个版本需要维护,手动迁移多个版本工作内容重复且效率较低。
2.人为的操作往往会出错,且出错时沟通成本较高。
因此我们在迁移的过程中实现了自动化的迁移流程,主要流程如下:
- 自动克隆原仓库的目标分支内容到 Monorepo;
- 删除需要统一的配置如 commitlint 等配置;
- 删除 babel, webpack 等相关重复依赖;
- 检测并替换,采用pnpm的 workspace protocal 链接的内部依赖引入方式;
- 删除 yarn/npm 相关的 lock 文件,并安装依赖生成最新的 pnpm-lock.yaml.
自动化迁移的实现,保证了迁移过程的快速且顺利的进行,各产品线的同学可以较为平滑的过渡到新的项目管理方式——Monorepo。
写在最后
数栈前端团队正式迁移到了 Monorepo,解决了之前 Multirepo 项目管理方式下的私有源维护成本高,工具/配置不统一,逻辑复用链路长且难以维护等问题。在迁移的过程中,实现了大部分迁移工作的自动化进行,并对重要的配置等进行了权限校验以进行限制和保护。整体提升了数栈前端团队研发的效率,降低了协作和沟通成本,有效实现了降本增效。
最后
欢迎关注【袋鼠云数栈UED团队】~
袋鼠云数栈 UED 团队持续为广大开发者分享技术成果,相继参与开源了欢迎 star
- 大数据分布式任务调度系统——Taier
- 轻量级的 Web IDE UI 框架——Molecule
- 针对大数据领域的 SQL Parser 项目——dt-sql-parser
- 袋鼠云数栈前端团队代码评审工程实践文档——code-review-practices
- 一个速度更快、配置更灵活、使用更简单的模块打包器——ko
- 一个针对 antd 的组件测试工具库——ant-design-testing
袋鼠云数栈前端从 Multirepo 到 Monorepo 研发效率提升探索之路的更多相关文章
- Molecule实现数栈至简前端开发新体验
Keep It Simple, Stupid. 这是开发人耳熟能详的 KISS 原则,也像是一句有调侃意味的善意提醒,提醒每个前端人,简洁易懂的用户体验和删繁就简的搭建逻辑就是前端开发的至简大道. 这 ...
- 袋鼠云出品!数栈UI 5.0全新体验升级,设计背后的故事
我们是袋鼠云数栈 UED 团队,致力于打造优秀的一站式数据中台产品.我们始终保持工匠精神,探索前端道路,为社区积累并传播经验价值. 前言 数栈作为云原⽣⼀站式⼤数据开发平台,从2016年发布第⼀个版本 ...
- 袋鼠云研发手记 | 开源·数栈-扩展FlinkSQL实现流与维表的join
作为一家创新驱动的科技公司,袋鼠云每年研发投入达数千万,公司80%员工都是技术人员,袋鼠云产品家族包括企业级一站式数据中台PaaS数栈.交互式数据可视化大屏开发平台Easy[V]等产品也在迅速迭代.在 ...
- 袋鼠云研发手记 | 数栈·开源:Github上400+Star的硬核分布式同步工具FlinkX
作为一家创新驱动的科技公司,袋鼠云每年研发投入达数千万,公司80%员工都是技术人员,袋鼠云产品家族包括企业级一站式数据中台PaaS数栈.交互式数据可视化大屏开发平台Easy[V]等产品也在迅速迭代.在 ...
- 华夏基金X袋鼠云:基金业数字化转型,为什么说用户才是解题答案?
"精准营销是以客户为中心,运用各种可利用的方式,在恰当的时间,以恰当的价格,通过恰当的渠道,向恰当的顾客提供恰当的产品." 这是学者许瑾在科特勒精准营销理论的基础上,从实践的角度对 ...
- 袋鼠云研发手记 | 袋鼠云EasyManager的TypeScript重构纪要
作为一家创新驱动的科技公司,袋鼠云每年研发投入达数千万,公司80%员工都是技术人员,袋鼠云产品家族包括企业级一站式数据中台PaaS数栈.交互式数据可视化大屏开发平台Easy[V]等产品也在迅速迭代.在 ...
- 数栈运维实例:Oracle数据库运维场景下,智能运维如何落地生根?
从马车到汽车是为了提升运输效率,而随着时代的发展,如今我们又希望用自动驾驶把驾驶员从开车这项体力劳动中解放出来,增加运行效率,同时也可减少交通事故发生率,这也是企业对于智能运维的诉求. 从人工运维到自 ...
- 袋鼠云旗下新公司云掣科技启航,深耕云MSP业务助推企业数字化转型
1983年3月15日,国际消费者联盟组织将3月15日确立为国际消费者权益日. 2019年3月15日,袋鼠云举办三周年年会. 一生二,二生三,三生万物.植树节后,万物生长. 年会现场,袋鼠云宣布成立新公 ...
- 览器全面禁用三方 Cookie 全栈前端精选 4月16日
览器全面禁用三方 Cookie 全栈前端精选 4月16日
- ByteHouse云数仓版查询性能优化和MySQL生态完善
ByteHouse云数仓版是字节跳动数据平台团队在复用开源 ClickHouse runtime 的基础上,基于云原生架构重构设计,并新增和优化了大量功能.在字节内部,ByteHouse被广泛用于各类 ...
随机推荐
- WPF开发必备
类库 1.XamlFlair The goal of the XamlFlair library is to ease the implementation of common animations ...
- 「tricks」平凡二分幻术
其实这个的标题叫 平凡线段树上二分幻术,因为这是一个民科在乱叫. 如标题所言,这个东西确实非常 trivial.碍于网络上没有一个成体系的文章供参考就只能自己来炒炒冷饭. 如果出了什么 bug 就当个 ...
- destoon运行流程二次开发必看
<?php 代码首先包含common.inc.php文件 在common.inc.php文件中,首先定义常量. define('IN_DESTOON', true); define('IN_AD ...
- QQ机器人整理合集
QQ机器人有什么用呢? QQ机器人可以实现包括自动回复.定时推送.发送图片QQ机器人,营销圈用的比较多,可以开发各种自动功能等等.用其制作的QQ机器人程序 机器人框架+插件 小栗子机器人 官网:htt ...
- RAC 环境中 gc block lost 和私网通信性能问题的诊断
声明:此文来自于MOS(Doc ID 1674865.1),整理在此以便于大家阅读学习. ■ 概要 在Oracle的RAC环境中,数据库会收集global cache 的工作负载统计信息,并把这些信息 ...
- WPF性能优化:Freezable 对象
Freezable是WPF中一个特殊的基类,用于创建可以冻结(Freeze)的可变对象.冻结一个对象意味着将其状态设置为只读,从而提高性能并允许在多线程环境中共享对象. Freezable的应用 我们 ...
- 通过Lambda函数的方式获取属性名称
前言: 最近在使用mybatis-plus框架, 常常会使用lambda的方法引用获取实体属性, 避免出现大量的魔法值. public List<User> listBySex() { L ...
- 源码搭建zabbix平台
1.基于lnmp部署zabbix监控平台; zabbix优点: 1.支持自动发现服务器和网络设备: 2.分布式的监控体系和集中式的WEB管理: 3.支持主动监控和被动监控模式: 4.基于SNMP.IP ...
- 04-23: dataclasses使用方法
vehicle_seeds: List[int] = dataclasses.field(default_factory=list) dataclasses 模块提供了一种简洁的方式来定义Python ...
- 让物体动起来,Unity的几种移动方式
一.前言 在大部分的Unity游戏开发中,移动是极其重要的一部分,移动的手感决定着游戏的成败,一个优秀的移动手感无疑可以给游戏带来非常舒服的体验.而Unity中有多种移动方法,使用Transform, ...