找回密码
 会员注册
查看: 27|回复: 0

Vision内核大升级——可视化搭建引擎Gems应运而生

[复制链接]

2万

主题

0

回帖

6万

积分

超级版主

积分
64454
发表于 2024-9-20 18:42:18 | 显示全部楼层 |阅读模式
近年来,前端领域逐渐掀起了一股低代码热潮,在经历前后数年的迭代演化后,低代码这一领域已是百花齐放,各家方案层出不穷,百家争鸣。在这样的缤纷繁杂的业态中,新一代低代码平台Vision及其核心搭建引擎Gems横空出世,加入到这场赛跑角逐之中。 我们应该从什么样角度去审视和设计我们的低代码平台?我想可以从业务和技术两个方向来做探讨: 在业务侧,以运营活动页为代表的C侧,以管理后台为代表的B侧,不同业务形态跨度之大,平台应该如何cover不同的业务场景? 在技术侧,页面编辑、版本管理、权限控制、预览发布、业务逻辑等不同能力、不同技术栈的功能被打包在同一个平台,平台应该如何组织和拆分这几者的联系? 本文将围绕Vision内核升级、Gems的诞生,以及可视化搭建的一些典型场景进行阐述,对以上问题的解决方案进行探索和讨论,希望能给读者带来一些启发。本文也是IMWeb团队低代码系列的开篇。Vision,是在线教育已经打磨了两年多的一站式通用运营平台,旨在帮助产品运营同学高效地完成活动页面的搭建、发布等工作的同时,也帮助业务开发效率和体验的不断提升。Vision跨过自己的一个个里程碑,截止到今日,除了在线教育的三大业务,也已经支持了部门外业务18个。在近一年的开发迭代中,Vision平台也针对活动页运营链路完善了一系列功能,诸如便捷的AB实验能力,开箱即用的线上数据透视能力等等。而另一方面,更接近搭建核心能力的升级,像水平布局、容器无限嵌套、组件间数据访问等能力却迟迟没有动工。背后的原因在哪?一、问题是什么?"我们似乎不太知道该从何下手增加这些能力 ",团队里负责一起维护Vision的小伙伴会发出这样的疑问。作为一个运营提效工具,它提效的方式是提供给运营同学便捷地可视化地搭建落地页的能力,不难发现,Vision的核心能力就是可视化搭建。然而,系统的设计是否能直观体现我们的核心能力?能力的边界又在哪?我们是否能清晰地辨析出新能力该在Vision的哪个子模块扩展,同时还保持着系统复杂度增长的平稳趋势?我心里也有着这些疑问,而答案几乎都是不明了的。可以看到,我们的模块划分是一个常规Web应用的方式,可视化搭建能力的核心并没有一个直观的形态,模块化的描述与可视化搭建领域的模型之间并没有建立合适的关联。在这样的设计下,由于缺乏对领域的抽象和基础模块的设计,很多工作都变得困难起来。比如我们想增加渲染协议检查相关的逻辑,我们需要仔细地阅读大量现有系统的代码,才能找到一个相对合适的切入点,完成功能的实现。更让人受阻的是,协议检查这个 涉及渲染流程 的能力落地,甚至需要同时发生在系统前端和后台的两个涉及渲染流程的模块中,编写类似的代码。这为系统代码的维护带来了额外的成本。我们需要一种更理想的设计方式,将Vision的核心能力直观地描述出来,将Vision系统的软件复杂度的增长压缩在一个可控的速度,从而帮助我们更稳固、高效地进行后续系统的开发与维护。来自团队另一类场景的诉求另一方面,团队内B侧需求量日渐庞大,持续有相当比例的人力投入到管理后台类系统开发中。这部分系统的重复度很高,都是重表单场景,很多时候就是各类表单的排列组合。同时大部分这类系统是给内部使用,对页面的质量、性能各方面要求相对C侧页面还是要稍低一些。这样的重复性与开发要求,持续投入在其中的同学未免会觉得自己的技术成长受限,管理后台页面的开发就好像成了一件苦差,谁都不乐意接。我们注意到,公司内其实已经存在用于解决管理后台场景的低代码方案,比如XPage,但是它目前仅在微信支付内部使用。我们很自然地考虑,是否能扩展Vision的系统能力,让其也能够支撑B侧场景。但几经推敲和讨论后我们放弃了这个思路。我们认为,运营场景与B侧场景在搭建页面的形态与搭建平台使用用户上存在着诸多差异,如果我们期望在一个搭建平台上解决两类问题,必然存在着一些折中的设计,为了同时满足两类场景的需求。最高效好用的工具一定是专注于某垂直领域提供深度解决方案的。因此,我们希望在上层建设另一个专注于管理后台系统搭建的平台,在新的平台上针对B侧场景提供最适合的产品设计;同时将Vision的核心搭建能力下沉,构建一个可视化搭建引擎,在其基础上,扩展更丰富的基础能力以支撑上层多样的应用场景。Vision遇到的问题,是软件工程的问题,是控制软件复杂度的问题;而来自团队的B侧需求,是产品能力复用的问题,是大框架下系统分层的问题。然而,它们似乎都指引着Vision往同一个目的地迈进......二、新的思路我们开始将Vision系统打碎,开始思考可视化搭建核心能力的边界在哪,可视化搭建核心的抽象可以是怎样的,换句话说,从Vision下沉的可视化搭建引擎的具体形态如何。Vision平台的产品视图,活动搭建、编辑页面,包含了活动页面编辑、保存、历史管理、权限控制、预览发布等等能力。这其中不少是更适合作为上层平台能力的,比如历史管理、活动发布等。这些都不是我们的引擎想要包含的内容。如果尝试用一句话来描述核心的搭建能力,那么首先,我们组织页面的方式是基于素材的拼装,然后页面搭建的结果,其实就是对页面组成素材的协议化描述,而页面的渲染,则是对这份描述的解释与执行。我们将上面这句话做一些拆解和抽象:我们需要提供对协议的解析与渲染的能力,我们把它叫做渲染器;协议从哪来呢,我们需要提供可视化组装协议的能力,就叫做编辑器;协议渲染过程所需对应的素材,那便是素材库;渲染器、编辑器、素材库,三个相对独立的基础库组成了我们的可视化搭建引擎。 它将作为承载可视化搭建领域核心能力的微内核,成为Vision以及上层其它各类贴合业务场景的搭建平台的基石,Gems应运而生。除了大模块的拆分,每个模块内部也进行了相当的抽象和设计,下图是一个总览:其中值得一提的是,编辑器中所见即所得的操作画布(模拟器)所依赖的渲染逻辑,我们统一收敛到了Renderer,然后通过编辑器中的 EditableEnhancer 为渲染组件提供编辑上下文特有的交互能力。 这带来了两个好处。1.降低了渲染相关逻辑改动的成本,即前面提到的涉及渲染逻辑的改动需要发生在多处的问题不复存在;2.减少了模拟器预览效果与最终发布效果的差异,因为渲染代码就是同一份。其它子模块的设计细节这里暂时不展开,后续可能进行系列文章总结,有兴趣的同学可以保持关注。三、新架构下的能力扩展在新架构的基础上,我们如愿进行了众多核心能力的扩展。这里从几个具体的场景切入,来看一看Gems具体能力项的设计与实现。栅格布局这里说的栅格布局,主要就是为了解决水平排列素材的场景,该场景在PC端页面中较为常见。原有的能力中,我们拥有普通的容器能力,容器里面可以放子组件。而栅格布局实现的方式则是提供一个栅格布局容器。可以看到,栅格容器看起来就是比普通容器多了几个“坑”,在添加组件时可以选择往哪个坑添加。那么,结合我们的整体架构进行需求分析:Renderer侧,从渲染协议开始看,本质上,栅格容器只需要一个额外的信息来描述子组件属于哪一个“坑” ;Materials侧,从素材定义看,栅格容器则比普通容器需要多定义一个信息,那就是容器需要有多少“坑”。其实分析到这,围绕这个“坑”的设计,似乎已经不局限于栅格容器了。所有需要有多个“坑”的容器组件,都可以拥有类似的抽象,像Tab组件、Table组件、模态窗等等。我们进行了如下的抽象和设计:“坑”=> 插槽=>slot;一个额外的信息来描述子组件属于哪一个“坑”=>渲染协议扩展,组件描述中增加slot字段;容器需要有多少“坑”=>组件定义中增加slots()配置项;到这,我们已经具备了渲染一个多插槽容器的基本条件,剩下的问题来到Editor,如何为这种携带插槽的容器赋予编辑态特有的一些UI和交互动作了,也就是让容器里的插槽可以被选中,指定往某个插槽添加子组件等等。得益于我们Editor与Renderer的架构设计,我们只需要在EditableEnhancer中扩展处理插槽的能力即可,具体的实现形式即为一个高阶组件,大致逻辑如下:将拥有插槽的容器的子组件按slot分组;为分好组的子组件包裹插槽组件,为插槽提供相应的UI和交互。const withSlots = (View) => {  return function WithSlots({ instance, children, ...otherProps }) {    const { slots } = instance;    return (              {          slots(instance).map((slot) => (                          {children.filter((child) => slot === child.props.slot)}                      ))        }          );  };};至此我们已经具备了提供栅格布局能力的所有关键要素。素材数据联动素材间的联动,其实Vision原有的设计里已经支持了,主要是借助事件系统实现的一套联动机制。这套联动模式在由明确UI(事件)驱动的场景下是很适合的,我们以点击按钮打开弹窗这个场景为例,简单回顾下Vision对此的描述方式:视角转换到我们新面临的B侧场景,我们试一试使用这套模型对常见的表单场景进行描述。我们假设有一个Input提供给用户输入,然后有另外一个Table依赖这个Input的值进行数据拉取,以及另一个Text需要展示Input的值。那么按上述联动动作的思路来完成,我们需要以下几步:1.首先在Input组件上提供一种自定义事件触发,比如输入变化,同时携带上改动的值;2.在Table上实现自定义动作(事件监听),比如更新参数,接收新的参数值并更新组件内部维护的数据;3.类似2,在Text上实现自定义动作,比如更新文本,接收新的文本内容并重新渲染;4.在Input上配置输入变化 分别触发Table和Text的更新参数、更新文本 动作。模型已经有些复杂了。这里的核心逻辑,Input其实是作为一个数据的生产者,对应的,Table和Text作为其数据的消费者。可以想象得到,我们需要为每一个拥有数据生产能力的素材,围绕其UI行为,实现类似上述步骤1的自定义事件触发,将数据发射出来;同时,为每一个拥有数据消费能力的素材(其实可以说是所有素材)实现类似上述步骤2/3的自定义动作。而且,当数据消费关系复杂时,上述步骤4的搭建配置,成本也是不容小觑的。显然,联动动作设计背后事件驱动的方式在这个场景下变得不那么适用。我们需要一种数据驱动的模式,我们需要一种组件间能进行数据共享的能力。我们为素材定义了新的接口能力—— 开放数据接口。简单的说,开放数据接口就是一个素材声明的可以被外部(其它素材)访问引用的数据接口声明。 区别于素材自身的静态数据,该开放数据是一个运行时的动态数据,并不固化于渲染协议中,数据也并不是由页面编辑者在搭建页面时产生。如上图,我们实现上面的表单场景就只需要简单的两步:1.在Input定义可供其它素材访问的数据项;2.页面搭建时,在需要消费Input数据的地方(此例为Table和Text的数据配置)通过Input的组件key(实例id)进行数据引用。整个具体的实现将由三个核心模块的密切配合共同完成:Materials提供数据接口的定义能力;Editor提供快捷配置数据变量及相关提示的组件配置表单能力;Renderer提供运行时数据对象的创建、数据分发及变量解析能力。每一个素材(包括组件、动作、插件)都可以定义自己拥有的可被其它素材访问的数据,同时素材数据的更新将会触发依赖侧的更新。最终的效果如下:组件模板在某一些场景下,我们希望一个组件被添加到画布中时能携带一些默认的样式或行为,比如模态窗组件。首先我们希望它能默认拥有比较常见的Footer(取消、确定按钮),但我们同样也希望模态窗的Footer部分可以相对自由的被定制,那么将Footer固化在模态窗实现内不会是一个好的方式。我们考虑将Footer部分作为模态窗的插槽之一,可以自由地置入子组件。所以现在就回到了最初的命题,我们需要一种能力,能够描述组件进入画布时的默认表现。可以分析得到,这个能力是Materials和Editor需要关注的。Materials提供素材默认表现的定义,而Editor则负责解析执行该定义,并赋予素材进入画布时以相应的行为。我们在Materials侧为每个组件提供了一种定义templates的能力,如下图:针对模态窗的场景,通过templates配置,为其定义了两种模板,其中弹窗(带默认Footer)的模板则自动携带了的“确认”、“取消”按钮。Editor拿到这份组件配置时,则会在组件面板中给出相应的模板以供搭建用户选择。组件的颗粒度与搭建灵活程度几乎是正相关的。组件颗粒度越细,那么搭建时可自由组合来支撑的页面多样性就越大。但与之而来的,是搭建成本的提高。反之组件粒度越粗,搭起来越简单,而灵活性又受限。组件模板能力的设计,有效缓解了搭建效率与搭建灵活性之间的矛盾 ,在维持细粒度、高灵活性的原子组件的同时,通过预设模板对原子组件进行组合的方式,为高频搭建场景提高了不少搭建效率。四、成果及未来展望从Vision中诞生出的Gems,现在已经成功替代了Vision原有的核心逻辑代码,也为Vision带来了新的栅格布局、数据联动等新能力。更重要的是,Gems让Vision的软件复杂度得到了控制,为系统的开发维护工作带来了指引,让一切系统的变更更加有迹可循。 另一方面,基于Gems,团队内专注于管理后台类页面搭建的Hulk系统也成功问世并投入实际生产之中。截止笔者发文,团队内已经在开心鼠排课系统、课堂章鱼哥、课堂人社系统等多个管理系统的页面使用Hulk搭建,得到一众好评,节省了大量开发人力。目前Gems仍在高速迭代与实践验证中,后续将开放给团队外使用,并逐步开源。届时欢迎大家前来使用、给予宝贵的意见!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 会员注册

本版积分规则

QQ|手机版|心飞设计-版权所有:微度网络信息技术服务中心 ( 鲁ICP备17032091号-12 )|网站地图

GMT+8, 2024-12-27 00:43 , Processed in 1.664584 second(s), 26 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表