Monorepo or 物料市场?结合工作实际情况对公司现有前端体系的思考

news2025/2/27 17:19:01

前言

去年年中基于若依vue前端框架进行了改造,加上后端的配合,我写了一套脚手架和项目中后台模板。中后台模板中包含了许多基础代码,比如登录/注册、路由、权限等等相关功能。这个中后台模板是基于我们实际开发定制的,所以跟通用的中后台模板(vue-element-admin)还不一样,可以认为是快速搭建系统的一种解决方案。

问题

在搭建了多个系统之后,我们遇到了点问题。项目模板在前期并不是特定稳定,有些功能需要进行调整,如果我们需要调整则需要在所有项目都进行手动调整,这会变得非常麻烦。随着系统的不断增加,这种每个系统都需要手动调整的方案势必会造成大量的资源浪费。所以我们开始讨论如何解决这个问题。

系统架构

在提出正式解决方案之前,我先简单介绍一下我们系统架构思路。我们前后端项目都是基于若依系统进行改造的,后端是使用Spirng cloud Gateway 将 api 分发到各个项目的微服务中,前端则是通过设置请求头来告知当前系统访问的项目。
应用部署架构

方案一 – Monorepo

Monorepo – 单体仓库基建方案。将多个开发项目放到一个项目中进行管理的一种手段。这种方案的优势和劣势也是显而易见的:

优势

  • 代码重用将变得非常容易:由于所有的项目代码都集中于一个代码仓库,我们将很容易抽离出各个项目共用的业务组件或工具,并通过 TypeScript,Lerna 或其他工具进行代码内引用;
  • 依赖管理将变得非常简单:同理,由于项目之间的引用路径内化在同一个仓库之中,我们很容易追踪当某个项目的代码修改后,会影响到其他哪些项目。通过使用一些工具,我们将很容易地做到版本依赖管理和版本号自动升级;
  • 代码重构将变得非常便捷:想想究竟是什么在阻止您进行代码重构,很多时候,原因来自于「不确定性」,您不确定对某个项目的修改是否对于其他项目而言是「致命的」,出于对未知的恐惧,您会倾向于不重构代码,这将导致整个项目代码的腐烂度会以惊人的速度增长。而在 monorepo 策略的指导下,您能够明确知道您的代码的影响范围,并且能够对被影响的项目可以进行统一的测试,这会鼓励您不断优化代码;
  • 它倡导了一种开放,透明,共享的组织文化,这有利于开发者成长,代码质量的提升:在 monorepo 策略下,每个开发者都被鼓励去查看,修改他人的代码(只要有必要),同时,也会激起开发者维护代码,和编写单元测试的责任心(毕竟朋友来访之前,我们从不介意自己的房子究竟有多乱),这将会形成一种良性的技术氛围,从而保障整个组织的代码质量。

劣势

  • 项目粒度的权限管理变得非常复杂:无论是 Git 还是其他 VCS 系统,在支持 monorepo 策略中项目粒度的权限管理上都没有令人满意的方案,这意味着 A 部门的 a 项目若是不想被 B 部门的开发者看到就很难了。(好在我们可以将 monorepo 策略实践在「项目级」这个层次上,这才是我们这篇文章的主题,我们后面会再次明确它);
  • 新员工的学习成本变高:不同于一个项目一个代码仓库这种模式下,组织新人只要熟悉特定代码仓库下的代码逻辑,在 monorepo 策略下,新人可能不得不花更多精力来理清各个代码仓库之间的相互逻辑,当然这个成本可以通过新人文档的方式来解决,但维护文档的新鲜又需要消耗额外的人力;
  • 对于公司级别的 monorepo 策略而言,需要专门的 VFS 系统,自动重构工具的支持:设想一下 Google 这样的企业是如何将十亿行的代码存储在一个仓库之中的?开发人员每次拉取代码需要等待多久?各个项目代码之间又如何实现权限管理,敏捷发布?任何简单的策略乘以足够的规模量级都会产生一个奇迹(不管是好是坏),对于中小企业而言,如果没有像 Google,Facebook 这样雄厚的人力资源,把所有项目代码放在同一个仓库里这个美好的愿望就只能是个空中楼阁。

从上述引用来看,monorepo的劣势对于我们小团队太过于沉重了。第一,我们没有足够的人力资源,这个问题还不单单在于项目权限的控制,更在与我们团队的人员水平和精力 – 是的,不得不承认团队水平参差不齐,并非所有人都愿意去付诸精力和汗水去学习。第二,我们已有的需求并不一定适合这种解决方式。我们的目的是快速搭建各个系统,前端并不需要微服务化,各个仓库之间没有明确调用关系。第三,对于现有系统的改造会很困难。我们每个系统都要重复的功能页面,但是我们并不能保证所有的前端页面都是一样的表现形式 – 可能针对某个特殊项目有功能调整。基于这一点我们如果要使用Monorepo的进行代码调整的话,我们需要将基础框架与页面、组件进行分离。这个工作量相当庞大,我们希望有更加轻量级的解决方案。

方案二 – 插件开发模式

插件开发模式 – 将系统分成shell和runtime模块,shell视为宿主,runtime视为插件。每个项目都包含shell和runtime两个部分,其中shell是包含基础的功能,包含开发、打包和基础的框架内容,runtime包含了业务相关模块。shell通过读取每个项目的配置文件进行调整,shell运行时会加载runtime的相关业务模块。

优势

这种开发方式好处是可以将 基础框架 与 业务开发 进行分离,如果后续我们需要升级shell 时就会变得相对简单(如果业务本身不需要修改shell的话),同时分离还降低了系统开发的复杂程度,使常规开发人员只关注业务本身的开发就好了。

劣势

  • 完全剥离框架与业务困难:目前的项目模板就是根据业务系统定制的,系统模板本身就集成了部分业务模块。但是我们并不能保证已经集成的业务模块不会发生变动或者需要新增一些新的公共业务模块。剥离基础框架和业务并不困难,困难的是我们的框架本身包含了公共的业务模块,我们无法对这块儿进行较好的处理。
  • 短期工作量大,难以渐进完成:框架杂糅了业务模块,如果需要采取插件模式开发,对现有的调整框架的调整较大。 一是要划分清楚框架与业务代码,对shell和runtime进行分离;二是要编写配置模块,明确需要读取哪些配置文件;三是已有的每个系统都需要按照这种较大的改动的方式去做,工作量大。

这确实是一种思路,但是我认为它适用的场景是那种 shell 与 runtime 分离比较容易的情况,类似于APP或者是小程序开发 – 有一个统一的shell运行各个需要加载的模块,降低不同开发人员使用不同的shell导致多个项目合并打包失败的问题。

方案三

物料市场。

物料即组成一个前端项目的不同单位,根据抽象粒度的不同,我们将物料从小到大分为 组件(component)、区块(block)和模板(template) 。在基于物料体系的开发中,我们使用模板物料来初始化前端工程,提供最佳实践,解决工程问题,再使用区块和组件像搭积木一样快速搭建页面。
物料分为 组件(component)区块(block)模板(template) 三种类型:

  • 组件(component):组件是组成页面的基本结构单元,是对局部交互逻辑的抽象和封装。通常需要设计和暴露属性、插槽、事件和方法等 API。使用者根据这些 API 直接使用,一般不需要做二次修改。
    从业务维度去看,组件又可分为基础组件和业务组件两种:
    • 基础组件:与业务无关的组件,基础组件保持统一的视觉规范,考虑高内聚低耦合的设计思想,例如 UButton、UInput、UTableView 等,在 Vusion 体系,官方维护 Cloud UI 基础组件库;
    • 业务组件:面向业务的组件,一般功能比较确定可复用,同时复杂度较高,例如用户选择器、计费卡片等。
  • 区块(block):区块可以理解为在页面中,由一些组件组合而成的代码片段。在一个页面中,使用者可以快速把某个区块的代码添加到自身项目里,进行二次修改。
  • 模板(template):项目的样板工程,包含了完整前端项目所有组成部分,包括布局、常用页面、基础插件、工程配置等,用户可以快速初始化项目。

我们已有中后台框架模板,就是对应到了物料中的模板这块儿。对于我个人而言我更加倾向于采取这种策略,原因如下:

  • 改造中后台框架调整工作量可控的。根据我们对物料的抽象程度不同,我们可以对项目进行不颗粒度划分。举例说明,我们将登录页面及其相关功能做成区块,那么新的项目就可以直接添加到进去,并根据业务要求进行修改。如果是需要调整,在将区块下载下来后,能做到快速更新的能力。

其他相关优点:

  • 最大化资源复用。项目,团队,成员之间轻松共享。
  • 提升迭代上下游协作效率。
  • 提升人效比。提升项目中前端开发人员的人效比,让前端做的更快、更多、更好;
  • 能力中台化。支撑业务快速发展。

参考链接:
All in one:项目级 monorepo 策略最佳实践
什么是物料
物料前端中台建设
从生产到消费,设计基于物料的前端开发链路
从业务组件库看前端物料生态
如何建设前端物料平台?

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

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

相关文章

SpringBoot——配置文件

项目中有许多公共使用的变量,例如端口号,连接数据库的配置,还有我们自己创建的变量,这些可以放到SpringBoot的配置文件中统一调配使用 properties 基本语法格式: keyvalue例如配置项目的端口号为8888: …

Bean注入到Spring方式

扒一扒Bean注入到Spring的那些姿势 配置文件的方式就是以外部化的配置方式来声明Spring Bean,在Spring容器启动时指定配置文件。配置文件方式现在用的不多了,但是为了文章的完整性和连续性,这里我还是列出来了,知道的小伙伴可以自…

Jetson Xavier NX设备将opencv和tensorrt链接到conda环境

注意安装的时候先查看设备旧版本的opencv,卸载干净后再装。 Jetpack4.6 opencv4.1.1 conda安装 过程翻一下之前的博客把,下面是创建环境开始 conda create -n py36 python3.6.9 OPENCV_EXTRA_MODULES_PATH/home/ta/open/opencv_contrib-4.1.1/modul…

白银走势图如何做空?

做现货白银的好处是,我们可以在白银走势图上做空,不再像股票那样只能先卖后买,还能先卖后买,这样我们做投资就多了一份从容!任何时候我们都能获得投资获利的机会,但是由于习惯了单向交易,我们要…

Sarsa算法讲解及实现

Sarsa算法讲解及实现 1. Q表格 我们使用表格来存储每一个状态 state, 和在这个 state 每个行为 action 所拥有的 Q 值。 Q即为Q(s,a)就是在某一时刻的 s 状态下(s∈S),采取动作a (a∈A)动作能够获得收益的期望,环境会根据agent…

java嵌入式持久化消息队列SMQ,改造自FQueue

一、说明之前项目中一直使用ConcurrentLinkedQueue做为缓冲队列(主要是单个项目内,单条改批量的场景,多个项目间使用的是rocketmq),虽然用着方便但是是纯内存的,如果项目发生异常崩溃内存队列中的数据就会全…

JavaSE学习day6 进制转换和idea的调试

1.进制 1.1 常见的进制分类(掌握) 学过计算机组成原理的同学可以跳过这里。 二进制 十进制 八进制 十六进制 1.2 二进制 计算机数据在底层存储和运算的时候,都是以二进制的形式操作的,了解不同的进制,便于我们对数据的运算过程理解的更…

个人博客推出了更多功能

背景 Web2.0的典型代表博客,吸引着粉丝们打造属于自己的个人博客,分享自己的学习经验,记录自己的日常生活。随着大厂的入局,我们可以很容易的申请自己的个人博客,但是弊端就是往往会被他们控制,甚至封号。…

汕头市农村生活污水治理“十四五”规划行动方案

汕头,简称“汕”,广东省辖地级市,北接潮州,西邻揭阳,南濒南海,东与台湾隔海相望,境内韩江、榕江、练江三江入海,是中国大陆唯一拥有内海湾的城市。今天就来为大家介绍,汕…

Windows系统实现命令行(CMD)关闭指定的IIS网站

一、需求说明我们部署在Windows服务器上的IIS网站,需要在特定的时间停止一会后在进行重新启动该网站。二、思路分析由于需要特定的时间停止后重启网站,则手动操作肯定是不行的,需要实现自动化操作:①特定时间操作可以使用Windows系…

聚观早报|王慧文要做「中国版 OpenAI」;Temu斥资近亿元赞助超级碗

点击蓝字 / 关注我们今日要闻:王慧文要做「中国版 OpenAI」;Temu斥资近亿元赞助超级碗;新东方在线股价收跌2.8%;ChatGPT带动的AIGC创业热潮要来了;传谷歌拆分其AR部门王慧文要做「中国版 OpenAI」 2 月 13 日&#xff…

CSS中的常见单位(px,%,em,rem,vw,vh,vmax,vmin,calc)

像素(px)&百分比(%) 像素(Pixel) 长度单位,相对于显示器屏幕分辨率而言,通常在不定义显示缩放比例的情况下,1px对应显示器屏幕上的一个像素点。早年的pc端展示的页面基本都用这个单位。 百分比(%) 相对长度单位,指占用的父…

电源模块 DC-DC直流升压正负高压输出12v24v转±110V±150V±220V±250V±300V±600V

特点效率高达80%以上1*2英寸标准封装电源正负双输出稳压输出工作温度: -40℃~85℃阻燃封装,满足UL94-V0 要求温度特性好可直接焊在PCB 上应用HRA 1~40W系列模块电源是一种DC-DC升压变换器。该模块电源的输入电压分为:4.5~9V、9~18V、及18~36VDC标准&…

对比Hashtable、HashMap、TreeMap有什么不同?

第9讲 | 对比Hashtable、HashMap、TreeMap有什么不同? Map 是广义 Java 集合框架中的另外一部分,HashMap 作为框架中使用频率最高的类型之一,它本身以及相关类型自然也是面试考察的热点。 今天我要问你的问题是,对比 Hashtable、…

HTTP协议——详细讲解

目录 一、HTTP协议 1.http 2.url url的组成: url的保留字符: 3.http协议格式​编辑 ①http request ②http response 4.对request做出响应 5.GET与POST方法 ①GET ②POST 7.HTTP常见Header ①Content-Type:: 数据类型(text/html等)在上文…

JavaSE系列 打基础版

JavaSE 笔记记录P1 Java概述1.1 java编译1.2 认识JDK、JRE1.3 下载jdk和配置环境变量1.4 开发注意事项和开发细节1.5 学习java之我的需求1.6 转义字符1.7 注释1.8 代码规范1.9 dos命令 了解P2 变量数据类型变量基本使用数据类型转换P3运算符P4 控制结构P5 数组、排序和查找P6面…

突破压缩极限的AI语音编解码器

I. Speech Codecs语音编码的目的是在保持语音质量的前提下尽可能地减少传输所用的带宽,主要是利用人的发声过程中存在的冗余度和人的听觉特性达到压缩的目的。经过了多年的发展,目前语音编解码器大致可以分为以下几类:波形编码,将…

c++ 指针、引用和常量

指针、引用和常量的关系_夜悊的博客-CSDN博客 1. ① 指针是对象,引用不是对象(在此可以理解为变量,一个变量是一个对象) 指针不必须初始化引用只是为一个已经存在的对象所起的另一个名字(别名)&#xff…

亚马逊云科技汽车行业解决方案

当今,随着万物智联、云计算等领域的高速发展,创新智能网联汽车和车路协同技术正在成为车企加速发展的关键途径,推动着汽车产品从出行代步工具向着“超级智能移动终端”快速转变。 挑战无处不在,如何抢先预判? 随着近…

安装 GPU 版本的 tensorflow 完整版本

前言: 之前安装的 CPU 版本的 tensorflow 一直出问题,索性就直接安装 GPU 版本的 tensorflow 了(有了GPU 就不能浪费)。 安装过程: 1)看自己有无 GPU,找到对应 GPU 的版本:任务管理…