作者简介:ck,携程后端开发专家,关注技术架构、高并发、性能调优等领域;Geralt,携程前端开发专家,关注前端框架及性能优化;Kaoru,携程资深前端开发工程师,关注前端性能及开发工具。
概述
PGClowcode平台是携程市场内容PGC团队搭建的主要用于后台页面开发的低代码平台,第一版于23年3月上线,截至10月平台已经拥有100+用户,在平台上开发了130+个应用和180+个页面。本文将主要介绍团队采用低代码平台的背景、方案调研、落地过程中遇到的问题以及解决方案,同时也大致介绍了该低代码平台提供的能力。
一、研究背景
1.1 为什么需要低代码平台
软件产品通常由客户端(App、小程序、网页)和运营后台组成,其整个生命周期需要不断地更新迭代,而在实际的迭代开发中经常会出现以下问题:
后台需求优先级低,排期经常被延期,通常使用配置中心等简易数据操作平台替代,不仅对运营人员不友好,而且产生了极大的生产风险
迭代需求涉及的前后端开发工作量不均衡,经常面临后台需求较多,但前端资源不足,服务端资源即便有空闲也没法帮忙支持后台的需求
不同业务间后台技术和组件大同小异,各业务反复造轮子,浪费时间和资源
开发人员开发工具类站点时,页面部分的工作需要付出较大的代价
针对这些问题我们也尝试了很多的解决方案,如要求开发人员全栈、剥离公共组件等,但结果都不太理想,经过充分的了解和分析,搭建低代码或零代码平台能在很大程度上解决这些问题。
1.2 需要什么样的低代码平台
低代码平台分为很多种,我们究竟需要哪种呢?经过将以上问题拆分细化和充分调研后,我们的低代码平台应该满足以下要求:
页面搭建方面:
界面友好、可视化,可以让研发和相关人员能通过拖拽的简单方式快速搭建UI
页面逻辑仅需写少量简单的代码或无需代码
支持满足日常需求的组件库
部署运维方面:
具有开发、部署、运维等完整的持续交付功能,最好能一键或自动化完成
安全合规方面:
支持权限管理机制,保证系统安全
具备完善的发布审批机制,能严格保证开发质量和生产安全
兼容性方面:
能嵌入已有后台页面,已有后台尽量少改动的嵌入其开发的页面
可扩展性方面:
支持用户自助化组件开发,并且能在平台上推广
二、现状分析
2.1 行业现状
目前国内外低代码或零代码产品不下百种,既有商业平台,也有开源项目,它们在企业内部用于各种运营后台、数据面板、办公系统等内部系统的开发,在B端提供商品管理、广告投放、商铺搭建等企业服务,在C端广泛用于活动页面、促销频道、广告频道等类型产品的搭建,不仅为企业节省了大量的开发成本、产生巨大的商业价值,同时也为用户提供了丰富多彩的软件产品。
虽然低代码种类繁多,但是每类低代码项目往往具有特定的业务属性,在不同的行业,不同的公司可能需要定制不同的组件,不同的流程,因此市场上很少有能适用于所有场景的平台,也很少有企业愿意去做通用平台。下面分析了目前比较流行的产品:
2.2 产品分析
阿里低代码引擎
LowCodeEngine(阿里低代码引擎)是国内最知名的低代码类产品之一,其完整的实现了《低代码引擎搭建协议规范》和《低代码引擎物料协议规范》,它通过完整的协议栈约定了各种物料的开发、使用、扩展、流通,并且提炼了企业级低代码平台的特性,遵循面向扩展设计的理念,奉行最小内核、最强生态的设计原则而设计的内核引擎。
目前其生态已经相当完备,并且提供了非常详细的文档和使用案例,也有大量的demo开源,其使用起来相对比较便捷。但它并没有提供完整的平台代码,使用者需要在其内核的基础上搭建面向用户的平台和服务系统,具有相当的开发成本。
腾讯低代码平台
腾讯的低代码产品包括搭建生成移动端H5页面的tmagic-editor开源项目和搭建管理端页面的无极低代码商业平台,其中tmagic-editor提供了完整的平台代码,使用者可以在开源社区将整个项目pull到本地部署使用,它具备自定义组件、插件、编辑器等扩展能力,内置了丰富的组件,提供了友好的可视化界面,通过拖拽+配置的方式开发页面。
但其限定于移动端H5页面的搭建,无法适用pc端页面开发的需求,大大限制了使用范围。无极低代码平台是商业化的面向企业付费使用的产品,具备管理端强大的开发能力,甚至结合了AI能力,能供面向企业丰富的解决方案,但它目前并没有开源。
开源低代码平台
在github上搜索lowcode关键词可以看到非常多的项目,他们所使用的技术、项目的形态、star数量、活跃的层度、使用场景各不相同,有些提供了完整的可视化界面,有些则需要通过配置文件或调用接口的方式生成页面或项目,总之需要花费较多的时间对比分析才能找到符合自身需求的项目。
总结
综上所述,我们最终决定选择一款开源程度比较高的项目(appsmith)作为蓝本,然后经过改造、开发搭建了PGClowcode平台。
三、平台功能介绍
PGClowcode平台功能主要包含页面搭建、组件开发平台两大部分。
页面搭建包含开发、预览、测试、发布、回滚、备份、恢复等常用功能。在这些功能的基础上,增加了"可视化拖拽"、"多用户协同开发"、"导入导出"、"多数据源"、"通知"等功能,形成了一个相当完善的开发体系。搭建的产物可以通过将平台上的应用或页面嵌入到已有的后台,或者反过来将已有的后台页面嵌入到平台,实现组合使用。
组件开发平台是对页面搭建能力的扩展,支持通过CLI构建本地项目,自定义开发新的组件以满足更复杂的业务需求。(此功能正在开发中,将在不久之后开放)
由于篇幅有限,下面将介绍几个主要功能。
3.1 用户和权限管理
平台拥有自己的用户管理体系,为了与携程的账号体系打通,接入了OIDC域账号认证,使用者无需额外注册账号,只需要使用携程域账号登录即可。
用户的权限做了充分的拆分,平台的所有功能对每个用户开放,只是对于用户私有的数据做了权限控制,权限定义的最小单位是工作空间(workspace),用户可以拥有多个workspace,每个workspace 定义了管理员(admin)、开发者(developer)、使用者(viewer)、测试者(tester)、审核者(reviewer)五个权限组。其中每个权限组对workspace下面的资源拥有不同的管理权限,这些资源包括数据源、应用、页面等,admin可以对workspace内的用户分配不同的权限组,从而对应用的开发、发布等流程上进行管理。具体各权限组的权限分配参考下表:
3.2 可视化应用开发
传统后台开发与采用低代码平台进行后台开发的流程区别如下图所示:
传统后台开发过程中需要开发者自身搭建开发环境,引入前端组件库如Ant Design,相同的功能需要自己提取组件,开发效率低效。
PGClowcode低代码平台提供了可视化拖拽的面板,支持页面复杂布局。组件栏支持40+种通用组件,并可以组合使用。
在页面绘制方面,通过将其拖入画板,调整位置布局,简单几步完成界面的设计,做到了所见即所得。相同功能可以在画布中复制粘贴,应用本身也支持导入导出功能,方便项目复制。开发变得灵活高效,避免了一些基本构建所产生的bug,达到了降本增效的效果。
在组件的属性值设定方面,可以通过可视化的输入或者通过自定义JS代码的方式进行复杂的逻辑绑定,并且也支持编写js代码完成复杂的交互逻辑。平台内置了多种js库,可以将数据绑定到组件上,在开发状态下能立即看到数据渲染的效果,使得在预览状态下可以边开发边自测。
3.3 流程管理
应用从开发态->测试态->发布态的流转十分便利。平台设计了不同角色,将测试、审核的流程精简化,各角色登录后可以看到应用的不同状态,应用在开发和审批后自动流转至下一状态,只需要简单几个流程即可完成。
1)开发人员(开发态):根据需求搭建、开发页面,然后发布到测试环境;
2)测试人员(测试态):在页面测试,保证其能满足需求,且不存在质量问题后点击Publish提交发布申请;
3)审核人员(发布态):在“待我审核”列表中找到审核申请。审批通过,应用自动完成发布。
3.4 备份与还原
开发平台支持了应用数据的备份和历史版本数据的还原。在开发状态下平台采用了自动保存的设计方案,由于多人同时开发时容易出现相互覆盖或操作冲突的情况,为了减少这种问题导致的返工成本,我们设计了备份和还原的功能。
和正常普通的应用一样,用户可以将每个稳定版本的开发态备份到系统,在之后的操作中需要回到某个稳定版本则直接选中目标版本还原即可。
下图展示了备份还原的操作界面。
四、架构和技术
PGClowcode平台采用了前后端分离架构。前端使用了react技术栈,并且集成了携程的多种公共框架和组件,依托于携程的CI/CD平台,实现了持续开发和交付的能力。服务端采用spring webflux框架,集成了cat、clog(携程日志系统)、mongo、credis(携程redis client)、qconfig(携程配置中心中间件,下文简称QC)、qmq(携程MQ中间件)等技术框架,完全融入了携程的服务技术栈,可以通过gitlab自动化编译打包,在captain(携程发布平台)上发布。
4.1 架构
如上图所示,PGClowcode平台的整体架构分为应用层、基础设施、服务层、数据层。
应用层是终端的两套平台系统,主要包括面向用户的低代码开发平台和面向开发人员的组件开发平台。
基础设施主要包含前端的基础框架、数据流控制以及抽象出来的前端可视的组件、页面和编辑器等概念。基础框架主要依托于React App和canvas技术通过axios库和服务端进行数据交互,通过Redux及相关插件来控制整个平台的数据流,最终展示成用户可见的组件、页面、编辑器等UI模块。
服务层主要由web层、service层和数据访问层组成,主要提供权限验证、流程管控、插件管理、消息通知、数据访问等服务。服务采用了微服务架构的设计,按照不同的领域和功能拆分成领域服务、通知服务和插件服务。
领域服务又根据不同的model细分为不同的模块,各自完成独立单一的功能;通知服务主要用于email、trippal、sms等消息通知;插件服务主要提供插件的加载、初始化、调用、卸载等相关功能的服务。数据访问在核心服务的下层,实现了针对多种数据源的访问和数据处理、校验的功能。
数据层主要用于存储元数据、应用数据、插件数据等,应用的备份数据存储于QC,并且通过QC实现跨环境发布。
下面两节主要对平台“组件的可视化拖拽实现”和“应用的开发-部署实现”两项比较核心的技术详细阐述。
4.2 组件的可视化拖拽实现
可视化拖拽组件是低代码平台的基本功能,在本平台中,用户可以在左侧组件库里选择任意组件拖拽到中间的编辑区域,并更改其大小。
在实现上述的拖拽功能时,我们会面临几个问题:
1)拖拽组件的过程中,组件的位置会实时变更,大量嵌套在一起的dom元素同时变更位置,会频繁触发浏览器的重绘制,导致性能的消耗。
2)人为的拖拽排布,很难保证组件之间的对齐和排版,页面最终效果难以达到代码实现页面的规整程度。
对于上述的问题1,平台的解决方案是依托canvas技术,在组件变更位置或者大小时,隐藏实际渲染在页面上的组件,并在编辑区域最上层渲染一层canvas,在原组件位置画出一个同等大小的色块来代替原组件,并用以示意用户,利用canvas画布的特性来处理组件位置及大小的变更,在用户结束拖拽动作后,根据色块在canvas中的最终位置及大小,重绘制一次组件,并隐藏canvas,展示出组件的最终效果。
在上述描述中可以看到,利用canvas可以极大程度的削减浏览器重绘制的次数,达到减少性能消耗的目的;选择色块来作为绘制对象而非原组件,既降低了技术实现的难度,又进一步降低了canvas绘制图形的性能消耗。
对于问题2,平台的解决方案是阵点系统,当用户拖拽组件到编辑区域触发渲染canvas的同时,页面上会绘制一层阵点并均匀的平铺在canvas上,当用户在canvas上拖拽色块变更其位置或者大小时,在色块的周边会绘制出同等大小的虚线边框,边框会根据色块当前的位置及大小动态的定位到合适的临近阵点上。阵点系统中,横向及纵向两个相邻阵点的间隔即为组件长宽的最小单位,组件的四角位置只能定位在阵点上。由此可见,在拖拽过程中,组件的位置及大小都在一定的限制之内,这可以保证最终绘制出来的页面的规整性。
以下为一次完整的组件拖拽流程示意图:
1)页面无拖拽操作,主编辑区域仅展示组件的静态状态,此时为展示态。
2)当用户开始拖拽组件以期改变其位置及大小的动态状态,为操作态。操作态又可以细化为拖拽开始、拖拽中、拖拽结束,三个状态。
当用户开始拖拽组件时,页面会从展示态变更为操作态。拖拽开始时,编辑区域内绘制canvas并铺设阵点,原组件变为不可见,在canvas内原组件的相同位置绘制同等大小的色块以及虚线边框;在拖拽过程中,色块会随着鼠标移动变更位置或者大小,其外部虚线边框也会随色块移动或变更大小,并实时定位在色块当前位置的最相邻阵点上;拖拽结束时,根据当前边框的最终大小及位置,重新绘制原组件,并隐藏canvas、阵点系统、色块以及虚线边框;页面由操作态变更为展示态,展示出组件的最新状态。
4.3 应用的开发-部署实现
应用的开发和部署的技术实现主要分为应用的数据结构、数据流转和多种角色协同三个部分,最后针对应用的数据备份与还原也做了简单的介绍。
4.3.1 数据结构
当前大多数主流的低代码平台最终的产物可能是代码,但PGClowcode平台最终的产物是数据,包括应用信息、页面信息、组件、组件之间的关系、action、数据源等都是以数据的形式存储在db上,由于页面的布局、组件嵌套、函数的绑定等各种实体间关系非常复杂,使用传统的关系型数据库无法保证数据结构稳定,因此采用了mongodb作为数据库。应用相关的collection主要包括了plugin、workspace、datasource、application、page、action、actioncollection,它们通过下图的关系构成了整个应用体系。
plugin主要用于定义平台支持插件的元数据信息,包括类型、插件包路径、参数、状态等属性。
workspace是应用开发的工作空间,它定义了空间内的用户组成、用户权限、数据源以及支持的插件集合。
application定义了应用的名称、主题、icon、状态等基本信息,另外为了查询便捷,也冗余了部分页面的信息。
page定义了页面的名称、布局、组件、组件的关系、组件与函数的绑定关系等。
datasource定义了外部数据访问的基础信息,如restapi、es、mongodb等外部数据访问的必要属性,为了避免重复配置,它的作用范围是workspace级别。
action定义了外部数据访问的具体配置数据,它必须依托于datasource,如restapi接口调用,datasource配置了服务的域名和是否需要实时鉴权,而action则配置路径、参数、运行方式,与datasouce不同的是它的作用范围是页面。
actionCollection是action或js函数的集合。
4.3.2 数据流转
应用数据主要是在不同的存储介质和不同的环境间流转,平台目前设计了三套环境FAT、UAT、PRO,平台通过QC的跨环境机制实现数据流转。
如上图所示,开发者在FAT上开发应用,应用数据以草稿态存储于DB,开发完成后将草稿态数据导出到QC的FAT环境,服务监听到QC的数据变更将草稿态copy到发布态,测试则可以在测试页面上看到开发提交的应用,测试完成后提交UAT发布申请,服务将发布态的数据导出到QC的UAT环境,此时审核者将收到待审核通知。
进入平台将待发布申请审核通过后,UAT环境的服务监听到QC数据变更将数据导入到DB,并且将应用数据状态置为发布态,然后可以在UAT的测试页面看到发布态的应用,当UAT测试完成后申请发布到生产(PRO),UAT服务将发布态应用数据导出到QC PRO环境,当审核者通过申请后则QC PRO的应用文件被发布,PRO服务监听到数据变更就将应用数据导入到DB,并置为发布态,此时应用的开发-部署流程结束,用户可以在生产环境的用户平台正常使用了。
4.3.3 多角色协同
对于应用的开发、测试、交付平台设计了多个角色,在整个需求开发的过程中每个角色能各司其责,保证应用能持续、稳定、高效迭代交付,如下图所示。
平台通过定义多个权限组来区分每个角色,当workspace被创建时这些权限组就会被创建出来,每个权限组定义了各自的权限,在每个受权限管理的资源中都有policies字段,它存储了能被操作的类型和权限组id的集合,当用户查询和操作时都会经过权限校验。
有了角色的定义,应用开发人员的协同就变得简单多了,如当应用发布测试时可以自动通知测试人员介入,提交发布生产申请时可以自动通知审核人员参与审核。
4.3.4 备份与还原
为了方便开发过程中多人同时开发,平台设计了备份还原功能,当用户点击备份时,服务将当前草稿态数据导出到QC,点击还原则将QC的数据导入到服务,覆盖当前DB中草稿态数据,得益于QC的版本管理功能,每次备份的数据都将存储起来,因此用户可以还原到历史的任意版本。
如上图所示,T1时刻新增一个备份v1,T2时刻QC中存在v1版本的备份数据,如果T2时刻再增加一个备份v2,到T3时刻QC存在v1和v2两个版本,如果在T3时刻将DB中的版本还原成v1,则DB中的数据会被还原成v1,与此同时会上传一个v3版本到QC,实际上v3和v1数据是一样的,相当于将当前数据的基准切换到了最新版本,之后的操作都是在这个版本的基础上做的,如果再需要还原到这个基准就可以快速完成。
五、规划与展望
目前PGC低代码平台已经具备了非常完整的功能,基本上完成了预期的目标,也产生较大的价值,但我们对于它的期望绝非只限于此,并且组建了稳定的支持团队,制定了明确规划,在之后的迭代开发中会不断地完善已有的功能和流程,而且会根据实际的需求和业内平台的调研继续增加更强大、便捷的功能。
5.1 搭建组件扩展平台
平台原有的组件是比较基本的组件库,未来会难以满足日渐复杂的业务需求,因此自定义组件的需求就会逐渐凸显出来,本平台基于Appsmith框架是支持自定义组件的,但是原有的自定义功能有如下几个问题:
1)原有的自定义组件功能,需要依托于完整的平台项目,在其widget文件夹下开发新组件,项目代码体量大,启动慢,且以开发组件为目的频繁更改提交平台项目并不利于平台项目的发布及管理。
2)原有的自定义组件功能并不适合多部门自定义组件的场景,没有相关的权限管理系统,所有自定义组件都会展示在页面上,随着时间的推移会造成组件库的臃肿以及增加编辑页面时查找使用组件的费力度。
为了解决以上问题,我们会从主项目中抽离出相关代码,搭建一套独立的组件开发项目,以达到和平台主项目分离、代码纯净、项目快速启动的目的。同时也会构建一套自定义组件的权限管理系统以便更好的管理各部门开发的自定义组件。
5.2 建立模板库
Ctrl+C和Ctrl+V可能是开发人员使用频率最高的按键组合,致使一些键盘不是“面目全非”就是“半身不遂”,试想一下,如果我们拿出来一键生成部署页面的功能,是否能让“久经磨难”的键盘依然“历久弥新”呢?没错,这是我们接下来的目标。
低代码平台的模板是指根据长期积累的经验,总结一些具有共性的通用方案,并且提炼成所有用户都能直接使用的页面或应用,收录到模板库中,当平台上的其他用户需要使用类似应用或页面时,只需要找到合适的模板,一键即可生成页面或应用,甚至能拿来即可用,无需做任何修改。后期可以允许建立团队自己的模板库,各成员可以搭建自己的模板专门供团队使用。