前言

随着功能和业务量级的飙升,前端代码量级也越来越大,管理运维的成本也进一步增加。

代码仓库的运营管理挑战也浮出水面。

主流方案有两种:一是multirepo式的分散式的独立仓库,二是monorepo式的集中管理,各有千秋,下面就结合实际场景一起深入了解下。

分散式管理:multirepo

即按照功能或者其他维度,将项目拆分为不同模块单独维护于各自仓库中。

使用场景

对于敏捷迭代快速开发的新需求,常规做法就是每个模块对应一个仓库,新的需求进行归类,可归入已有仓库则进行迭代,不满足则新建仓库。

优势

1.灵活

不同模块独立维护,与其他模块天然隔离。各个模块可以选择适合自己的风格、工具等。

2.安全

得益于模块的拆分,权限控制较为自然。

开发时只关注相关部分,不会误操作其他内容。

发布上线,对其他模块无感知。

问题

作为传统的管理组织方式,发展演进这么久,必然会存在一些限制。突出体现在协作和管理成本上。

1. 管理成本

常见的项目交接时,每个人都负责了一堆项目、账号等,只能手动梳理,还存在漏掉的可能。我当初经历过几次大的调整,交接的真是一脸懵逼和心痛。来个需求才发现还有个仓库一直处于遗忘的角落。

2. 协作成本

涉及多个项目开发时,本地开发需要打开多个IDE在其中切换。

对于本地调试等也是个繁琐的过程,虽然存在npm link等方式。

3. 依赖升级

这种场景一般出现在依赖的核心模块上,特别是自行开发的基础依赖,不得不升级时简直一言难尽,数目直逼上百的项目,每个都要修改发布一次。

上面说的是业务模块,对于开源或者公司内部基础性工具,升级这里的问题更显著一些。对于程序员俩说,出现问题解决问题就是,因此集中式的管理模式就出现了。

集中式管理:monorepo

monorepo 的核心观点是所有的项目在一个代码仓库中。严格的统一和收归,以利于统一的升级和管理。

不过这并不是说代码没有组织的随意存放。相反,在文件目录上体现出管理结构的要求更高,否则可维护性更低。

例如Babel,每个模块都在指定的packages目录下。

优势

既然是基于问题的演进,其实优势比较明显,就是multirepo的局限的解决。

例如协作、运营管理等成本降低。

不过monorepo也不全是益处,相反其局限也比较明显。

问题

1. 项目体积增加

随着项目的发展,体积会逐渐增大,甚至成为巨无霸项目体积几个G。

自然带来一些问题:

  • 获取时间变长

    拿babel举个例子,虽然只有130M,但时间已经增加不少,更遑论上G的存在。

    http://xxdy.tech/img/mono.gif[动图太大,始终上传不成功,只能放个链接了。。。]

  • 编译耗时增加

    很自然,如果每次还是全部编译的话,开发、部署时的等待时间会相当的长

2. 安全性

全部功能就这样暴露在所有开发者面前,安全性是个大问题。

误操作的可能性,如果仅仅寄希望于开发者素质和codereview时的人工复检是不可靠的。

解决方案

当然对于比较成熟的模式,解决方案也是形成了沉淀的。

1. 多模块管理工具

针对复杂的项目模块,自然需要有贴合实际的管理工具。

例如lerna,自我定位就是:

A tool for managing JavaScript projects with multiple packages

至于详细用法,大家可以通过官网查看。

2. git稀疏检出

针对开发者只关注相应内容的解决方案可以依托git来实现的。

Git在1.7版本后,已经支持只Checkout部分内容,即稀疏检出(sparse checkout)

稀疏检出就是本地版本库检出时不检出全部,只将指定的文件从本地版本库检出到工作区,而其他未指定的文件则不予检出(即使这些文件存在于工作区,其修改也会被忽略)。

也就是我们可以在工作区只关注相关的模块,虽然文件全部pull了下来,但展示和管理式会忽略其他文件,即使展示了其他文件并进行了修改,修改依然会被忽略。

例如babel中我们只展示 babel-cli 内容部分,操作如下:

// 创建文件夹
mkdir demo && cd demo
// 初始化git
git init
git remote add origin https://github.com/babel/babel.git
// 打开 开关
git config core.sparsecheckout true
// 指定目录
echo "packages/babel-cli/" >> .git/info/sparse-checkout
// 获取代码
git pull origin master

这样,我们ls可以查看到文件内容只有:

packages/babel-cli

如果需要修改展示目录,直接修改.git/info/sparse-checkout,即可,然后重新进行checkout

echo "packages/babel-cli/" >> .git/info/sparse-checkout
git checkout master

这样增加了安全性。

扩展:浅克隆

稀疏检出只是展示上的部分,本身仍然包含所有的文件和历史。如果只关注最近的提交,可以通过浅克隆实现。

使用:

git clone --depth 2 https://github.com/babel/babel.git

不过浅克隆限制较多,一般用于对远程版本库的查看和研究。

  • 不能从浅克隆版本库克隆出新的版本库。
  • 其他版本库不能从浅克隆获取提交。
  • 其他版本库不能推送提交到浅克隆版本库。
  • 不要从浅克隆版本库推送提交至其他版本库,除非确认推送的目标版本库包含浅克隆版本库中缺失的全部历史提交,否则会造成目标版本库包含不完整的提交历史导致版本库无法操作。
  • 在浅克隆版本库中执行合并操作时,如果所合并的提交出现在浅克隆历史中,则可以顺利合并,否则会出现大量的冲突,就好像和无关的历史进行合并一样。

结束语

本文简单介绍了不同的仓库管理模式理念和一些实践方式,个人理解有限,抛砖引玉,欢迎一起讨论。更多内容请转雨打梨梦三村边

参考文章

monorepo仓库管理方式探秘的更多相关文章

  1. pnpm 的 workspace 实现 monorepo 工程

    前言 前端多个包管理的的方式一般都是采用monorepo的方式去管理,之前都是使用的lerna的workspace去管理.这段时间包管理切换到了pnpm上,它也有worksapce,可以支持monor ...

  2. Vue3 企业级优雅实战 - 组件库框架 - 1 搭建 pnpm monorepo

    前两篇文章分享了基于 vite3 vue3 的组件库基础工程 vue3-component-library-archetype 和用于快速创建该工程的工具 yyg-cli,但在中大型的企业级项目中,通 ...

  3. 漫谈Puppet4

    激动人心的改进 速度,速度,还是速度 稳定性和鲁棒性的提升 全新的Parser “不变"的agent 不兼容的改动 包管理方式的变化 配置文件/目录的路径变化 其他路径变化 Director ...

  4. RFID系统的选择

    RFID系统的选择关键在于:1.对自身需求的明确:2.以业务为导向:满足今天的需求,又支持明日的发展:3.选择合适的解决方案供应商. RFID技术改变传统的仓库管理方式,能为您企业提高作业效率,节省大 ...

  5. 一文看懂Vue3.0的优化

    1.源码优化: a.使用monorepo来管理源码 Vue.js 2.x 的源码托管在 src 目录,然后依据功能拆分出了 compiler(模板编译的相关代码).core(与平台无关的通用运行时代码 ...

  6. 大家都能看得懂的源码(一)ahooks 整体架构篇

    本文是深入浅出 ahooks 源码系列文章的第一篇,该系列已整理成文档-地址.觉得还不错,给个 star 支持一下哈,Thanks. 第一篇主要介绍 ahooks 的背景以及整体架构. React h ...

  7. 一个实用的 vite + vue3 组件库脚手架工具,提升开发效率

    无论是 vue2 全家桶还是 vue3 + vite + TypeScript,组件库的使用几乎大家都会,但自己开发一个独立组件库就不是每个人都掌握的,因为搭建组件库的基础开发环境,就会让很多同学望而 ...

  8. Apache Spark探秘:三种分布式部署方式比较

    转自:链接地址: http://dongxicheng.org/framework-on-yarn/apache-spark-comparing-three-deploying-ways/     目 ...

  9. 基于 Lerna 管理 packages 的 Monorepo 项目最佳实践

    本文首发于 vivo互联网技术 微信公众号 https://mp.weixin.qq.com/s/NlOn7er0ixY1HO40dq5Gag作者:孔垂亮 目录 一.背景二.Monorepo vs M ...

随机推荐

  1. HDU 1081 To The Max【dp,思维】

    HDU 1081 题意:给定二维矩阵,求数组的子矩阵的元素和最大是多少. 题解:这个相当于求最大连续子序列和的加强版,把一维变成了二维. 先看看一维怎么办的: int getsum() { ; int ...

  2. mysql原来是按自然日统计。怎么可以用今天10点到次日10点这样统计???

    关于网友提出的" mysql原来是按自然日统计.怎么可以用今天10点到次日10点这样统计???"问题疑问,本网通过在网上对" mysql原来是按自然日统计.怎么可以用今天 ...

  3. GMTC2019|闲鱼-基于Flutter的架构演进与创新

    2012年应届毕业加入阿里巴巴,主导了闲鱼基于Flutter的新混合架构,同时推进了Flutter在闲鱼各业务线的落地.未来将持续关注终端技术的演变及趋势 Flutter的优势与挑战 Flutter是 ...

  4. redux之createStore方法底层封装模拟

    首先在看代码之前让我们一起回顾下redux的思想吧   首先redux就是一个MVC思想的框架,他总体是遵循数据的单向流动自顶向下流动 在我们仓库中有一个initState用来存储着我们的初始数据 另 ...

  5. python代码实现树莓派3b+驱动步进电机

    python代码实现树莓派3b+驱动步进电机 之前买了个树莓派,刚买回来那会儿热情高涨,折腾了一段时间,然后就放那吃灰了.前几天忽然想起来这个东西了,决定再玩玩儿,于是就从某宝上购买了一套步进电机.驱 ...

  6. AtCoder Regular Contest 059

    C - いっしょ / Be Together 数据比较小,暴力就挺好的.O(n^2)可过的好题 #include <bits/stdc++.h> using namespace std; ...

  7. protobuf_1

    我使用的是最新版本的protobuf(protobuf-2.6.1),编程工具使用VS2010.简单介绍下google protobuf: google protobuf 主要用于通讯,是google ...

  8. E - Count on a tree 树上第K小

    主席树的入门题目,这道题的题意其实就是说,给你一棵树,询问在两个节点之间的路径上的区间第K小 我们如何把树上问题转换为区间问题呢? 其实DFS就可以,我们按照DFS的顺序,对线段树进行建树,那么这个树 ...

  9. input标签前台实现文件上传

    值得注意的是:当一个表单里面包含这个上传元素的时候,表单的enctype必须指定为multipart/form-data,method必须指定为post,浏览器才会认识并正确执行.但是还有一点,浏览器 ...

  10. js实现方块的碰撞检测

    文章地址:https://www.cnblogs.com/sandraryan/ 个人感觉.方块的碰撞检测比圆形麻烦~~ <!DOCTYPE html> <html lang=&qu ...