Monorepo(单体仓库)与MultiRepo(多仓库): Monorepo 单体仓库开发策略与实践指南

news2024/10/7 8:28:55

🌟 引言

在软件开发的浩瀚宇宙里,选择合适的代码管理方式是构建高效开发环境的关键一步。今天,我们将深入探讨两大策略——Monorepo(单体仓库)与MultiRepo(多仓库),并通过使用现代化的包管理工具 pnpm,手把手搭建一个功能完善的 Monorepo 仓库。✨

🌱 Monorepo 与 MultiRepo:各显神通

在这里插入图片描述

上图为MultirepoMonorepo对比图,从图中我们可以简要归纳:

  • Multirepo是由多个仓库组成的项目管理方式,每个仓库有着独立的工作流、组件与配置
  • Monorepo则将不同仓库整合成为一个仓库,并共享工作流、组件与配置。

🌲 Monorepo:统一即是力量

Monorepo——想象一座巨大的知识宫殿,每个房间(项目或模块)紧密相连,共享相同的血脉(配置与依赖)。👑

  • 🌈 优点

    • 集中的管理: 🤝 统一的依赖、工具链,简化维护与升级。
    • 代码共享: 🔄 跨项目复用代码,减少重复劳动。
    • 协同作战: 👥 提升团队间的并行开发效率与代码审查质量。
  • 🔥 挑战

    • 仓库膨胀: 📦 随着项目增多,仓库体积可能庞大,影响克隆速度。
    • 权限分层: 🔒 需精细权限控制,防止信息误触。

🌳 MultiRepo:独立自主的花园

MultiRepo——设想一系列精致的花坛,每一处都是独立的世界,拥有自己的气候(配置)与植被(代码)。🌸

  • 🌟 优点

    • 清晰边界: 🛡️ 每个项目界限分明,便于独立管理和部署。
    • 轻便灵活: 💨 小型仓库,克隆快,利于新手上手。
    • 工具自由: 🛠️ 各项目可选最适合的工具链和流程。
  • 🔥 挑战

    • 依赖分歧: 💔 版本不一致,管理复杂度上升。
    • 共享难题: 🔀 共享代码需额外机制,如私有包管理。

选择Monorepo还是MultiRepo,犹如在协作效率与独立灵活性之间寻找平衡点。🎯

总结来说,monorepo倾向于**增强协作和代码一致性,而multirepo则更强调项目独立性和简单性**。选择哪种模式取决于具体团队规模、项目间关联程度、基础设施支持等因素。

在github上我们可以看见无论是element plusAnt design以及vue,以及其他社区开源的项目都是使用的monorepo 方案来管理他们的项目

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


📊 Monorepo 目录结构概览

一个健康的Monorepo,其目录结构应清晰有序,如下所示:

root
├── .husky       # Git钩子,自动化代码检查
├── node_modules # 依赖存放
├── packages     # 各项目或包的集合
│   ├── proj1    # 项目1
│   ├── proj2    # 项目2
│   └── ...
├── .cz-config.js # 提交信息格式化
├── .gitignore   # Git忽略规则
├── .prettierrc.js # Prettier格式化配置
├── pnpm-workspace.yaml # pnpm工作区配置
└── README.md    # 项目总览

🛠️ 搭建 Monorepo

🚀 pnpm-原生支持Workspaces

选用pnpm作为Monorepo项目中的包管理器主要有以下几个理由:

🎯 硬链接与缓存机制

  • pnpm使用硬链接和符号链接(软链接)来避免在磁盘上重复存储同一依赖的不同副本,显著减少存储空间占用。
  • 它还引入了内容寻址存储(CAS)的概念,只存储唯一的内容块,从而优化了存储和下载效率。

🎯 更快的速度与更低的磁盘占用

  • 由于依赖的共享和链接机制,安装和更新依赖时的速度更快,尤其是对于包含大量重复依赖的Monorepo项目,优势更加明显。
  • 即使在大型项目中,也能保持良好的性能和较低的磁盘占用。

🎯 原生支持Workspace

  • pnpm natively支持Workspaces(类似于yarn workspaces),只需简单的配置就可以轻松管理多个包或项目,这些项目可以在一个仓库中共享依赖。

🎯 扁平化依赖结构

  • pnpm保证了依赖树的扁平化,但同时也保持了依赖包之间的隔离,降低了版本冲突的可能性。

🎯 简洁的CLI工具

  • pnpm提供的 CLI 工具对于Monorepo的日常管理任务(如安装、更新、清理依赖)十分友好,可以直接在多个项目中执行命令。

🎯 生态系统兼容性

  • pnpmnpm生态系统的兼容性很高,能够无缝对接大部分支持npm/yarn的工具和流程。

因此,在构建和维护Monorepo时,pnpm凭借其高效的空间利用、快速的依赖管理以及对多项目工作区的良好支持,成为了一个理想的选择。尤其在需要频繁交互和更新多个项目共享依赖的场景下,pnpm的优势尤为突出。

🔥 Monorepo中pnpm常用命令

  • 安装/添加依赖

    # 在所有工作区内安装全局依赖
    pnpm add <dependency> -w
    
    # 在单个工作区内安装依赖
    pnpm add <dependency> -w <workspace-name>
    
    # 安装本地工作区间的依赖
    pnpm add <workspace-package>@workspace:<workspace-name>
    
  • 更新依赖

    # 更新所有工作区的依赖
    pnpm update -w
    
    # 更新单个工作区的依赖
    pnpm update -w <workspace-name>
    
  • 清理无用依赖

    # 移除未在package.json中声明的依赖
    pnpm prune -w
    
    # 清理缓存
    pnpm cache clean
    
  • 列出工作区依赖

    # 显示所有工作区及其依赖关系
    pnpm list -a
    
    # 显示单个工作区的依赖树
    pnpm list -w <workspace-name>
    

🔩 创建Monorepo

  • 初始化

    pnpm init
    
  • 修改package.json的信息

    {
        "name": "仓库名称",
        "version": "1.0.0",
        "description": "",
        "...": "..."
    }
    
  • 根目录新建packages目录

    mkdir packages
    
  • 新建pnpm-workspace.yaml文件

    touch pnpm-workspace.yaml
    
  • 声明对应的工作区

    # pnpm-workspace.yaml
    packages:
        # 存放所有项目的目录
        - 'project/*'
        # 存放组件的目录
        - 'components/*'
        # 组件库使用的示例代码
        - 'examples/*'
        # 存放文档
        - 'docs/**'
        # 存放公共库(配置文件、工具函数、模版等)
        - 'shared/**'
    
  • packages目录创建相应的工作区目录以及示例项目

    # 进入`packages`目录
    cd packages
    # 新建`project`工作区
    mkdir project
    # 新建`components`工作区
    mkdir components
    # 新建`examples`工作区
    pnpm create vite examples
    # ...
    
  • 将所有项目用到的共同依赖的dependenciesdevDependencies添加到根目录的package.json中,并在根目录下载依赖到仓库全局锁定,后面创建的项目将沿用这套依赖

    pnpm install -w
    

到此,monorepo已经准备就绪,接下来就可以进行仓库的eslintprettiercommitlinthusky等代码规范以及提交规范的配置了。


🎯 总结

Monorepo策略通过pnpm的高效管理,实现了代码库的集中与共享,极大提升了大型项目或团队的协同效率。从目录结构规划到依赖管理,每一步都旨在构建一个既强大又灵活的开发环境。无论你是初创项目还是成熟团队,掌握Monorepo的构建与管理,都将是你软件开发之旅的强大助力。🚀


🔐 相关链接

  • pnpm的安装与配置: pnpm的安装与配置(Windows/macOS)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1642246.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ThreeJS:两种场景雾

雾 ThreeJS提供了Fog类&#xff0c;用于创建线性雾的效果&#xff1b;提供了FogExp2类&#xff0c;用于实现指数雾的效果。 雾效果常用于模拟真实世界中视觉深度递减的效果&#xff0c;也可以用于创建某些艺术效果。即&#xff1a;当物体距离观察者越远&#xff0c;雾就越密&am…

Windows系统下安装Mosquitto的步骤(6)

接前一篇文章&#xff1a;Windows系统下安装Mosquitto的步骤&#xff08;5&#xff09; 本文内容参考&#xff1a; Windows下搭建MQTT服务器_mqtt服务器软件-CSDN博客 特此致谢&#xff01; 在前一篇文章中&#xff0c;笔者通过MQTTX实现了通过图形界面环境收发MQTT消息。但是…

SPARC VScode EIDE GDB 使用配置

前言 搞了多年的SPARC 最近接触了VSCODE插件感觉好用。想想看不是能方便调试和编译SPARC&#xff0c;决定使用开源的SPARC仿真环境和编译器来试试。感觉的却不错&#xff0c;借此献给使用SPARC的朋友们。安装 1.找微软官方的下载VSCODE. 2.电机左边的方块形状的图标&#xff0…

由于找不到msvcr110.dll,无法继续执行代码的解决方法

在日常使用计算机的过程中&#xff0c;可能会遇到系统提示缺少msvcr110.dll文件的情况&#xff0c;这一问题往往导致某些应用程序无法正常运行。幸运的是&#xff0c;有多种方法可以有效应对这一困境&#xff0c;帮助您的计算机恢复顺畅运作。以下是解决计算机丢失msvcr110.dll…

【游戏行业】2024年电子游戏分类,国内游戏产业报告,发展趋势

文章目录 一、电子游戏分类1、传统游戏分类2、混合手游分类3、二次元、开放设计、调查问卷 二、游戏产业报告1、游戏产业数据2、游戏公司名单&#xff08;独角兽&#xff09;3、营收与利润&#xff08;对比互联网、国企&#xff09; 三、发展趋势1、游戏行业上下游2、游戏行业趋…

正点原子[第二期]Linux之ARM(MX6U)裸机篇学习笔记-12-蜂鸣器

前言&#xff1a; 本文是根据哔哩哔哩网站上“正点原子[第二期]Linux之ARM&#xff08;MX6U&#xff09;裸机篇”视频的学习笔记&#xff0c;在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。…

PX4二次开发快速入门(三):自定义串口驱动

文章目录 前言 前言 软件&#xff1a;PX4 1.14.0稳定版 硬件&#xff1a;纳雷NRA12&#xff0c;pixhawk4 仿照原生固件tfmini的驱动进行编写 源码地址&#xff1a; https://gitee.com/Mbot_admin/px4-1.14.0-csdn 修改 src/drivers/distance_sensor/CMakeLists.txt 添加 add…

01-MySQL 基础篇笔记

一、MySQL 概述 1.1 数据库相关概念 数据库&#xff1a;&#xff08;DB&#xff1a;DataBase&#xff09; 存储数据的仓库&#xff0c;数据是有组织的进行存储 数据库管理系统&#xff1a;&#xff08;DBMS&#xff1a;DataBase Management System&#xff09; 操作和管理数…

IoTDB 入门教程 基础篇⑨——TsFile导入导出工具

文章目录 一、前文二、准备2.1 准备导出服务器2.2 准备导入服务器 三、导出3.1 导出命令3.2 执行命令3.3 tsfile文件 四、导入4.1 上传tsfile文件4.2 导入命令4.3 执行命令 五、查询六、参考 一、前文 IoTDB入门教程——导读 数据库备份与迁移是数据库运维中的核心任务&#xf…

最小费用流相位解包裹

% test_cunwrap.m % % Matlab script to test Costantinis unwrapping % Author: Bruno Luong <brunoluong@yahoo.com> % History: % Orginal: 27-Aug-2009clear all; close all; clc; I1=double(imread(E:\zhenlmailcom-E8E745\华为家庭存储\.public_files\博士阶段\小…

[stm32-1]LED闪烁LED流水灯蜂鸣器

1、LED闪烁&LED流水灯&蜂鸣器 1.使用RCC开启GPIO时钟 2.使用GPIO_Init函数初始化GPIO 3.使用输入或输出函数控制GPIO口 RCC常用的3个库函数&#xff1a; void RCC_AHBPeriphClockCmd(uint32_t RCC_AHBPeriph, FunctionalState NewState); void RCC_APB2PeriphClockC…

C++中的reverse_iterator迭代器结构设计

目录 reverse_iterator迭代器结构设计 reverse_iterator迭代器基本结构设计 operator*()函数 operator()函数 operator->()函数 operator!()函数 rbegin()函数 rend()函数 operator--()函数 operator()函数 测试代码 const_reverse_iterator迭代器设计 reverse…

【数据结构】第四讲:双向链表

目录 一、链表的分类 二、双向链表的结构及实现 1.带头双向链表的结构 2.创建节点 3.初始化 4.尾插 5.打印 6.头插 7.尾删 8.头删 9.在pos位置之后插入数据 10.删除pos节点 11.查找 12.销毁 个人主页&#xff1a;深情秋刀鱼-CSDN博客 数据结构专栏&#xff1a;数…

java基于云计算的SaaS医院his信息系统源码 HIS云平台源码

目录 云HIS功能模块 1、预约挂号&#xff1a; 2、药库管理&#xff1a; 3、门诊医生站&#xff1a; 4、门诊费用&#xff1a; 5、药房管理&#xff1a; 6、治疗室&#xff08;门诊护士工作站&#xff09;&#xff1a; 7、统计分析&#xff1a; 8、财务管理&#xff1a;…

vue 时间轴页面 自己的写法 欢迎交流指正

<div class"first-box"><!--贯穿线--><div class"vertical-line-wrap"><div class"vertical-line"></div><div class"vertical-line-arrow"></div></div><!--开始--><div c…

数据存储-SD卡存储

手机自带内存较小&#xff0c;不适合存储大量数据&#xff0c;一般&#xff0c;大量数据都会采用外部存储&#xff0c;如&#xff1a;服务器存储、SD卡存储、数据库存储等。 本文讲解在SD卡上存储数据&#xff0c;并实现对数据的读和写。 整体思路&#xff1a;静态权限声明、动…

第五篇:通信脉络:探索计算机外设与总线体系的精髓

通信脉络&#xff1a;探索计算机外设与总线体系的精髓 1 引言 在这个技术日新月异的时代&#xff0c;理解计算机系统的基本构成要素 —— 总线和外设 —— 对于每个从事技术工作的人来说都是至关重要的。这些组件不仅是计算机通信的基石&#xff0c;也直接影响着系统的性能、效…

非对称齿轮的跨棒距算的对不对

前面有一期咱们聊了非对称齿轮《》&#xff0c;非对称齿轮的齿厚测量一般都为跨棒距。最近研究了下计算方法&#xff0c;对计算结果的正确性做了下验证。 在MATLAB中编制了相关的计算程序&#xff1a; 齿轮的模数4&#xff0c;左侧分度圆压力角25&#xff0c;右侧分度圆压力角…

CARIS12如何设置kmall船型文件?

最近我们对船上多波束EM2040D的采集软件进行了升级&#xff0c;从SIS4.3升级至SIS5。当使用CARIS11/12处理kmall数据时&#xff0c;发现往返横切海底线性目标时有10-20m错位。 ​编辑​ 我们开始怀疑SIS5采集的设置有问题&#xff0c;似乎跟时间延迟有关系。但是改了如下图两…

JAVA系列 小白入门参考资料 接口

目录 接口 接口的概念 语法 接口使用 接口实现用例 接口特性 实现多个接口和实现用例 接口间的继承 接口 接口的概念 在现实生活中&#xff0c;接口的例子比比皆是&#xff0c;比如&#xff1a;笔记本上的 USB 口&#xff0c;电源插座等。 电脑的 USB 口上&am…