俯瞰 Monorepo,别一番风景!

简介: 本故事简要地介绍了 Monorepo 的 What 和 Why,重点篇幅在于搭建一个好用的 Monorepo 工程时应该考虑的点。可以作为你在选择工具时的条件,也可以作为你在搭建 Monorepo 工程时查漏补缺的参考。希望这对你有所帮助,哪怕只是一点点 \^O^

image

写在最前

本故事简要地介绍了 Monorepo 的 What 和 Why,重点篇幅在于搭建一个好用的 Monorepo 工程时应该考虑的点。可以作为你在选择工具时的条件,也可以作为你在搭建 Monorepo 工程时查漏补缺的参考。希望这对你有所帮助,哪怕只是一点点 \^O^

“在这个 AI 内容生成泛滥的时代,依然有一批人"傻傻"坚持原创,如果您能读到最后,还请点赞或收藏或关注支持下我呗,感谢 ( ̄︶ ̄)↗”

What?- 独立和关系

丹尼尔:蛋兄,好久不见,今天我们来聊聊 Monorepo 吧!

蛋先生:Monorepo?就是把多个项目放在同一个仓库里的那种吗?

丹尼尔:是呀,感觉上就是把一堆代码库简单地堆在一起

蛋先生:你说得不太准确,我觉得 Monorepo 最重要的是俩关键字:独立和关系

丹尼尔:怎么说?

蛋先生:独立是指这些项目本身是完整的,一般都拥有开发、测试,发布等完整的生命周期,而不是简单的包含一堆代码文件的文件夹

丹尼尔:哦,这个我明白了。那关系呢?

蛋先生:关系是指这些项目之间存在一定的关联,比如它们属于同一个业务领域,或是有依赖关系,而不是毫无关联地硬堆在一起

丹尼尔:懂了!

Why?- 更好地协作

丹尼尔:那用这个 Monorepo 有什么好处呢?我以前一个项目一个仓库不也挺好的吗?

蛋先生:这里科普一下,一个项目一个仓库有一个专用的名词叫 Polyrepo。我认为 Monorepo 最关键的好处在于项目与项目之间的协作

丹尼尔:怎么说呢?

蛋先生:比如共享代码以减少重复工作方面。当你在开发应用 B 时,如果发现应用 A 中已经实现了很多相似的逻辑,那么你需要把共享逻辑抽取到一个独立的库 α,然后修改应用 A 和应用 B 以依赖于库 α,因为这一切都在同一个仓库中完成,非常方便,操作成本较低

丹尼尔:确实,如果采用 Polyrepo 的方式,我得新建一个仓库,把共享逻辑抽取出来,然后通过本地 link 的方式来开发调试。一切就绪后,还得发布到 npm,再在应用 A 和应用 B 中安装依赖。而且每次修改都需要重复这个过程,真是麻烦

蛋先生:再比如库修改可能导致项目不稳定方面。当一个被依赖的库进行迭代升级时,特别是有大的变更时,如果没有及时沟通以采取相应的措施,就会导致各种问题,潜在的风险非常大

丹尼尔:Monorepo 不会有这个问题吗?

蛋先生:在 Monorepo 中修改是原子的,即当你修改库 α 时,同仓库的应用 A 和应用 B 都能及时感知到变更。例如,你删除了某个接口的入参参数,应用 A 和应用 B 会立刻报错,这样就能及时发现并解决潜在风险

丹尼尔:这样确实挺棒的

蛋先生:最根本的原因是 Polyrepo 带来了隔离,而隔离影响了协作。Monorepo 的目标则是为了更好地协作。就像部门间协作和部门内协作,显然同一个部门内的协作效率更高,沟通成本也更低

丹尼尔:一语中的!

How?- 舒适地开发

➥ 初始化阶段 - 脚手架

丹尼尔:那采用 Monorepo 的形式来组织项目,我应该怎么做呢?

蛋先生:我们一起来走一走应用开发的历程,看看需要有哪些工作吧

丹尼尔:好啊

蛋先生:有两种开局方式。一种是全新开始,这样的话你需要一个能生成 Monorepo 大仓的脚手架

丹尼尔:恩,很体贴

蛋先生:不过这种情况发生的概率较低,通常是一次性的。更常见的是在已有的 Monorepo 仓库中增加新项目。这是经常需要做的事情,所以我们可以提供多种脚手架代码生成器来快速初始化一个项目,比如创建 TS 工具库项目、React 应用项目,或者是 TS CLI 项目等等

丹尼尔:确实,常用的项目类型是可以枚举出来的。有了这些工具,后续增加项目就轻松多了,想想就很爽!那另一种开局呢?

➥ 初始化阶段 - 依赖安装

蛋先生:另一种开局是你准备在一个已存在的 Monorepo 大仓上进行开发工作。这时,你的第一件事应该是安装依赖,对吗?

丹尼尔:恩,没错

蛋先生:不过,大仓里可能有很多项目,你总不能一个一个项目进行安装依赖吧,所以需要有一个可以一次性安装全部项目依赖的能力

丹尼尔:对啊,我可不想把时间浪费在一个个项目里 cd 来 cd 去的

➥ 开发阶段 - 任务编排

蛋先生:无论哪种开局,接下来都是进入到开发阶段了。假设你在开发应用 A,而应用 A 依赖库 α,那么你是不是得先确保库 α 有可用的构建产物?

丹尼尔:是啊,所以第一步就是得知道应用 A 依赖了哪些同仓库中的其他库,并且提前对它们进行构建。但如果依赖关系比较复杂,就难搞了

蛋先生:正是如此。所以,我们希望能够不用手动处理这些依赖,只要对应用 A 进行构建,就能自动处理它所依赖的所有库的构建

丹尼尔:那就太好了!

蛋先生:这就需要任务编排了。我们可以配置任务之间的协作关系,比如在执行某个任务之前,需要先执行哪些任务,这些任务是串行还是并行执行等等

丹尼尔:哦,任务编排还真好用

➥ 开发阶段 - 一致命令

蛋先生:好了,万事俱备,你可以开始本地开发调试了

丹尼尔:哦,那我先看看项目的 README,找找本地开发调试的指引

蛋先生:不用那么麻烦,直接执行 dev 命令吧。无论你是在开发应用项目还是库项目,无论是用 JavaScript 还是 Java,开发就运行 dev,构建就运行 build,测试就运行 test,等等。这样你就不会有任何心智负担

丹尼尔:哈哈,老早就想这样了

➥ 开发阶段 - 影响检测

蛋先生:开发过程中,你发现依赖的库 α 提供的接口有点小问题,现在你准备对应用 A 所依赖的库 α 进行修改

丹尼尔:哦,反正都是在同一个仓库,修改起来挺方便的

蛋先生:但我们得确保这个改动不会影响到依赖该库的其他项目。至少在我们可控的范围内,比如同一仓库中依赖该库的其他项目。所以,我们需要一种自动检测机制来识别哪些项目受到了影响,然后对这些受影响的项目进行单元测试等操作,以确保它们的稳定性

➥ 开发阶段 - 依赖分析

丹尼尔:蛋兄果然很谨慎啊

蛋先生:咳咳~。其实,这一切都需要借助依赖分析能力。当 Monorepo 的规模越来越大时,依赖关系也会变得越来越复杂。我们需要通过依赖关系图,清晰地了解各项目之间的联系和影响,从而做到对项目状况了如指掌

➥ 开发阶段 - 依赖权限

蛋先生:你现在是库 α 的主要负责人。有一天,你发现了一些并不想对外暴露的 API 被仓库内的其他项目使用,结果你在修改这些 API 时就不得不考虑对这些项目的影响

丹尼尔:啊,虽然我是声明了 export,但这只是为了库内部的其他代码使用。可其他项目却可以通过深层导入来依赖这些 API

蛋先生:嗯,所以我们需要在工程层面上建立机制,防止这些 API 被误依赖

➥ 开发阶段 - 修改权限

蛋先生:库 α 虽说是由你主要负责的,但是由于代码库是放在一起的,其他拥有大仓权限的同学也就有权限进行修改。但是你并不希望他们随意修改库 α 的代码,至少要经过你的同意

丹尼尔:是啊是啊,这真的很重要!

蛋先生:所以我们需要引入类似 OWNER 的机制,对这些修改权限进行限制,以确保代码的稳定性和一致性

➥ CI 阶段 - 本地计算缓存

“注:CI 阶段的能力,不仅仅只用于 CI,开发阶段也是可以享用,只是为了剧情需要这么安排而已”

蛋先生:好了,项目修改完毕,提交。CI 开始工作了,然后你发现每次 CI 构建都非常慢

丹尼尔:嗯,我加点戏哈。我喝了一杯咖啡,再回来一看,好家伙,CI 还在跑。这样可不行,得优化性能了,不然我快要崩溃了

蛋先生:好吧,这戏加得... 回到正题。这是因为该项目直接或间接依赖了同一仓库中的好几个其他库。所以,每次构建实际上都需要构建多个项目。优化性能的思路之一就是减少不必要的计算,增量执行就变得非常重要。因此,我们需要引入本地计算缓存,缓存计算结果,避免对没有修改的库进行重复构建

丹尼尔:本地缓存,我懂

➥ CI 阶段 - 分布式任务执行

蛋先生:性能优化的另一个思路是加速必要的计算

丹尼尔:昨加速捏?

蛋先生:可以采用分布式任务执行。将一些可以并发执行的任务分配到不同的服务器上并行处理,实现在更短的时间内完成任务。这样做虽然会增加一定的成本,但对于大型项目来说,是非常有效的性能提升方案

丹尼尔:听上去好高级的样子

➥ CI 阶段 - 远程计算缓存

蛋先生:虽然使用了本地缓存,但每个服务器都需要先构建一次才能生成本地缓存。如果我们把缓存的位置移到远程云端,是不是就可以进一步优化性能呢?

丹尼尔:Nice! 这样就可以共享缓存了

➥ 发布阶段

蛋先生:最后,我们需要把库 α 发布到 npm 上去,因为它提供的功能非常通用,不仅仅局限于当前的项目仓库内

丹尼尔:那就赶紧发布吧!

蛋先生:发布阶段,根据需要,利用任务编排就可以了

新的问题

丹尼尔:听起来 Monorepo 灰常好啊,都使用这种方式得了

蛋先生:Monorepo 确实突破了 Polyrepo 的隔离问题,但这样开放的结构也带来了读权限的问题。如果你的大仓中的部分项目需要由第三方团队来开发,但你又不希望他们能看到其它项目的内容,那么 Monorepo 就无法解决这个问题了

丹尼尔:啊,那怎么办呢?

蛋先生:这种情况下,你可以考虑将这些项目作为 git submodule 分离出去。这样一来,大仓中的其它项目仍然可以在工作空间内直接依赖这些分离出去的 git submodule 项目

丹尼尔:那有啥需要注意的地方吗?

蛋先生:要注意的是,git submodule 的项目就不能通过工作空间直接依赖大仓中的其它项目了,它们需要通过 npm 中央仓库来进行依赖管理

丹尼尔:好咧,这一聊,天色已晚

蛋先生:嗯,今天就先聊到这里,就此别过吧

丹尼尔:拜拜!

写在最后

为什么不直接写一个使用某个工具(比如 Turborepo)来搭建 Monorepo 项目的教程呢?因为我相信聪明的你,只需要阅读官方文档,就可以轻松上手了

不同工具工作方式有所不同,但都是围绕 Monorepo 来提供能力的。我们应以不变应万变,掌握表面之下的东西,这样才能更加灵活地应对各种变化

“亲们,都到这了,要不,点赞或收藏或关注支持下我呗 o( ̄▽ ̄)d”

目录
相关文章
|
14天前
|
存储 人工智能 弹性计算
阿里云弹性计算_加速计算专场精华概览 | 2024云栖大会回顾
2024年9月19-21日,2024云栖大会在杭州云栖小镇举行,阿里云智能集团资深技术专家、异构计算产品技术负责人王超等多位产品、技术专家,共同带来了题为《AI Infra的前沿技术与应用实践》的专场session。本次专场重点介绍了阿里云AI Infra 产品架构与技术能力,及用户如何使用阿里云灵骏产品进行AI大模型开发、训练和应用。围绕当下大模型训练和推理的技术难点,专家们分享了如何在阿里云上实现稳定、高效、经济的大模型训练,并通过多个客户案例展示了云上大模型训练的显著优势。
|
17天前
|
存储 人工智能 调度
阿里云吴结生:高性能计算持续创新,响应数据+AI时代的多元化负载需求
在数字化转型的大潮中,每家公司都在积极探索如何利用数据驱动业务增长,而AI技术的快速发展更是加速了这一进程。
|
9天前
|
并行计算 前端开发 物联网
全网首发!真·从0到1!万字长文带你入门Qwen2.5-Coder——介绍、体验、本地部署及简单微调
2024年11月12日,阿里云通义大模型团队正式开源通义千问代码模型全系列,包括6款Qwen2.5-Coder模型,每个规模包含Base和Instruct两个版本。其中32B尺寸的旗舰代码模型在多项基准评测中取得开源最佳成绩,成为全球最强开源代码模型,多项关键能力超越GPT-4o。Qwen2.5-Coder具备强大、多样和实用等优点,通过持续训练,结合源代码、文本代码混合数据及合成数据,显著提升了代码生成、推理和修复等核心任务的性能。此外,该模型还支持多种编程语言,并在人类偏好对齐方面表现出色。本文为周周的奇妙编程原创,阿里云社区首发,未经同意不得转载。
|
14天前
|
人工智能 运维 双11
2024阿里云双十一云资源购买指南(纯客观,无广)
2024年双十一,阿里云推出多项重磅优惠,特别针对新迁入云的企业和初创公司提供丰厚补贴。其中,36元一年的轻量应用服务器、1.95元/小时的16核60GB A10卡以及1元购域名等产品尤为值得关注。这些产品不仅价格亲民,还提供了丰富的功能和服务,非常适合个人开发者、学生及中小企业快速上手和部署应用。
|
21天前
|
缓存 监控 Linux
Python 实时获取Linux服务器信息
Python 实时获取Linux服务器信息
|
4天前
|
云安全 存储 弹性计算
|
6天前
|
云安全 人工智能 自然语言处理
|
9天前
|
人工智能 自然语言处理 前端开发
用通义灵码,从 0 开始打造一个完整APP,无需编程经验就可以完成
通义灵码携手科技博主@玺哥超carry 打造全网第一个完整的、面向普通人的自然语言编程教程。完全使用 AI,再配合简单易懂的方法,只要你会打字,就能真正做出一个完整的应用。本教程完全免费,而且为大家准备了 100 个降噪蓝牙耳机,送给前 100 个完成的粉丝。获奖的方式非常简单,只要你跟着教程完成第一课的内容就能获得。
|
24天前
|
自然语言处理 数据可视化 前端开发
从数据提取到管理:合合信息的智能文档处理全方位解析【合合信息智能文档处理百宝箱】
合合信息的智能文档处理“百宝箱”涵盖文档解析、向量化模型、测评工具等,解决了复杂文档解析、大模型问答幻觉、文档解析效果评估、知识库搭建、多语言文档翻译等问题。通过可视化解析工具 TextIn ParseX、向量化模型 acge-embedding 和文档解析测评工具 markdown_tester,百宝箱提升了文档处理的效率和精确度,适用于多种文档格式和语言环境,助力企业实现高效的信息管理和业务支持。
3984 5
从数据提取到管理:合合信息的智能文档处理全方位解析【合合信息智能文档处理百宝箱】
|
3天前
|
人工智能 C++ iOS开发
ollama + qwen2.5-coder + VS Code + Continue 实现本地AI 辅助写代码
本文介绍在Apple M4 MacOS环境下搭建Ollama和qwen2.5-coder模型的过程。首先通过官网或Brew安装Ollama,然后下载qwen2.5-coder模型,可通过终端命令`ollama run qwen2.5-coder`启动模型进行测试。最后,在VS Code中安装Continue插件,并配置qwen2.5-coder模型用于代码开发辅助。
245 3