低代码页面搭建平台在百瓶的实践

公众号名片 作者名片

前言

大家好,我是本次内容的分享人君二,今天我要讲的主题是「低代码页面搭建平台在百瓶的实践」。接下来就带大家了解一下我们为什么要做这样一个系统,以及我们是如何成功完成这个系统的。

我们的低代码系统服务于我们公司的产品——百瓶 APP,它是一个专业的威士忌社区,大家如果想分享喝酒的日常、买酒卖酒都可以上我们的 APP。

我们在完成业务方面向 C 端用户的需求时,发现大量电商推广页面的逻辑复杂度和交互程度都比较低,但却要消耗大量的开发资源。同时在后台管理系统的开发过程中,我们也发现一些相同套路的页面在不同场景下需要重复开发,即使我们封装了开箱即用的业务组件,也难逃成本不低的心智负担。

因此,在调研了市面上一些解决方案后,我们决定搭上低代码这趟高铁。

传统模式的痛点

传统模式开发流程

我们在设计系统时一定不能脱离业务,自嗨并不能为我们带来真正的价值,因此我们首先要知道在做这个系统之前,我们的效率瓶颈在哪些地方。在传统模式中,不管是瀑布式开发还是敏捷式开发,都逃不过需求从运营或产品方提出,然后经过一系列开发、测试再到上线。

我们可否省去开发、测试、运维这些环节?

移动端

移动端的痛点

在开发移动端电商推广页时,我们要达成快速交付、低维护成本的效果。此时,我们通常会对页面进行充分的组件化,比如图片组件、文本组件、商品列表组件、优惠券组件等,但是即便这么做了,我们开发测试一个页面也可能要花费两到三个人力的一天左右的时间。

此外,为了应对运营随时更改运营策略、调整页面布局,我们可能会在后台管理系统中增加诸多配置,但是即便如此,依然不能涵盖所有的维护场景。

管理后台

管理后台的痛点

除了移动端页面外,我们在开发后台管理系统的页面时也有诸多痛点。众所周知,后台管理系统其实就是一个可视化的数据库,里面的内容万变不离其宗,无非是数据获取、数据展示、用户输入、控制校验、数据提交。这其中大部分的页面形式都是相同的,如果我们为了减少开发工作量而抽离大量业务组件,也免不了这些业务组件的控制逻辑开发以及记忆负担。而如果我们继续封装出业务性更强的开箱即用组件,就会发生自由度不够高、组件属性越加越多等不易于定制和维护的现象。

平台设计思路

既然我们决定要向低代码的方向发展,在踏出这一步之前我们就必须思考清楚,我们是对开源项目进行改造还是完全自研。我认为这个问题需要根据实际情况而定。

如果你要做的项目更侧重展示,并且在未来只会加入少量个性化的内容,那我建议寻找一个优秀的低代码开源项目进行改造,市面上有诸如 h5-Dooring 这样优秀的移动端低代码平台,也有 Ant Design Landing 这样基本不需要开发的 PC 端低代码平台。

反之,自研会更好。

开发方向的思考

需求收集

自研前的准备需要尽可能地详尽充分,毕竟我们谁也不想写到一半把方案推倒重来。

百瓶的页面搭建系统在布局以及操作形式上模仿了 h5-Dooring 项目,左侧是组件库,中间是画布,右侧是配置属性。此外,我们还需要规划组件库以及组件对应的配置,设计数据结构,拆分整个闭环的各大模块,设计模块的细节等等。

h5-Dooring

在不同端上,页面布局形式会有比较大的差异。

  • 移动端页面在布局时由于横向尺寸较小,偏向于楼层式布局,偶尔会有少数悬浮组件;
  • PC 端页面在布局时由于整体尺寸较大,更偏向于自由布局,随心所欲。

在推荐使用哪种方式之前分享一下我们在实践过程中 踩的坑

起初我们选择了楼层式的上下堆叠布局,原因是移动端页面布局简单,运营只需要叠加图片、文字、商品列表、超链接等组件就能实现某一次的促销。虽然我们预见到了将来可能会有组件套组件的情况发生,但是并没有重视。然后 618 来临了,京东、淘宝这些大型电商平台琳琅满目的会场页给了我们一个沉重的打击。我们的搭建系统做不到那种程度,根本就无法支持页面中有标签栏或导航栏这样的容器组件存在。618 过后我们不得已使用了一种极不优雅的方式解决组件嵌套的问题,维护和操作成本高昂。

之后,我们在开发面向开发的后台可视化搭建系统时,发誓绝不重蹈覆辙。这次选择了比较复杂的自由布局,采用树形结构表示组件间的关系,这才体会到「自由布局真香」。

所以要尝试可视化搭建的小伙伴,给你们一个忠告:不要犹豫,直接上自由布局

布局形式

除了面向不同设备需要有不同的设计,面向不同的使用者也需要考虑系统要做到什么程度。就拿组件库种类和组件配置来说。

  • 当系统面向运营人员,那么组件需要尽可能地业务化,减少使用者的认知成本,包括组件的配置,以通俗易懂的名词为主,并且整体配置数量要尽可能精简;
  • 当系统面向开发人员,那么组件需要尽可能地原子化,增加使用者的自由度,组件配置也需要尽可能地细化,以代码中出现的名词为主,并且配置项在需求范围内要尽可能详细。

组件配置对比

渲染依据的确定

著名的 Pascal 之父说过一句话:程序 = 数据结构 + 算法,我认为数据结构应当先于算法设计,数据结构在很大程度上会决定算法的走向。因此开始正式编写设计方案时,我选择从数据结构的设计开始。

我们在搭建完一个页面之后,实际导出结果大致有两种方向。

  • 导出 DSL 描述文件;
  • 导出页面源代码。

描述文件的优点是:

  • 渲染无关:它不关心渲染器是如何实现的,你用 Vue 也好 React 也好都没问题,每个组件的渲染效果都由组件自己管理,可以做到主题切换、结构动态化、千人千面等效果;
  • 方便部署:因为它只是页面结构的描述,在渲染器是现成的情况下,它能够在页面搭建完毕后直接进行线上发布,无需构建;
  • 二次编辑:由于它与渲染无关,描述文件始终不变,因此它可以很方便地进行二次解析与编辑。

但是它也有一个明显的缺点:

  • 二次开发困难:如果我们碰到了组件库或者行为库中不存在的个性化需求,就需要二次开发,而使用描述文件就很难进行自定义组件的插入或是控制逻辑自定义。

直接导出源代码除了二次开发方便外,我觉得缺点占大多数:

  • DevOps 成本升高:从搭建完毕到构建部署的自动化链路需要投入更多精力;
  • 老数据不易处理:渲染框架更换后,处理老数据极其复杂;
  • 二次编辑成本升高:对源代码进行页面二次编辑时需要借助语法分析,生成 AST 树或其它树形数据结构来恢复现场,这个操作需要团队有更多的人力成本与试错机会。

我们选择了第一种以 DSL 描述文件作为页面导出的基础,为了解决自定义组件和自定义逻辑注入的问题,我们采用了自定义插槽组件以及上下文逻辑调用的方式,在一定程度上实现了鱼和熊掌兼得。

数据结构选型

BBCS 全景

完成数据结构的设计之后,我们对模块进行了一个大概的拆分。整个系统由几大重要模块构成:

  • 编辑器
  • 自由布局系统
  • 行为中心系统
  • 数据中心系统
  • 渲染器

编辑器负责了组件库的呈现、自由布局形式的搭建、组件的配置、虚拟数据中心的描述以及逻辑编排。

渲染器负责了依赖自由布局的组件渲染、编排逻辑的执行以及数据流转的调度。

数据中心是最核心的模块,它保存了页面运行时的数据状态,组件在运行时无论是读取数据进行展示还是存储用户输入数据,都是通过数据中心进行的。

行为中心是交互时的重要依仗,因为我们的系统不仅需要支持页面布局结构的搭建,也要能进行逻辑编排。编辑器的逻辑编排系统生成的行为描述文件,将由渲染器的行为调度器执行具体逻辑。

整个闭环大概是这样的:

  1. 在编辑器中通过接口返回数据结构或其它需要半自动化构建出虚拟数据中心描述;
  2. 捋清页面需要的逻辑,进行逻辑编排,并将原子逻辑的输入输出数据字段与虚拟数据中心正确地关联;
  3. 进行页面结构的搭建,正确地将组件的输入输出数据字段与虚拟数据中心关联,并在需要时将组件事件与行为(编排的逻辑)挂钩;
  4. 完成页面编辑,移动端直接上传描述文件至服务器,管理后台导出描述文件至目标项目以便支持二次开发;
  5. 渲染器接收服务端返回的描述文件或项目中静态的描述文件进行渲染。

系统架构图

如何实现自由布局

前面我们重点提到了自由布局的好处,那它应该如何实现呢?

在编辑器层面,如果有比较适合本身产品形态的三方拖拽处理库等现成的解决方案,那强烈建议直接使用,不用重复造轮子。我们选择了自己处理拖拽事件来实现自由布局,要点就是处理好拖拽事件的拦截与落点位置的计算。我们在编辑器中对自由布局做了这些操作:

  • 设置组件库和画布中的组件使之可被拖拽;
  • 组件被拖拽时保存组件的信息;
  • 画布中的组件接收并拦截拖拽移动事件,在全局状态中维护自身与事件触发位置信息;
  • 根据当前拖拽到达的组件类型(容器与非容器型)与事件触发位置计算落点位置并在画布中有所表示;
  • 拖拽放下时根据计算的落点位置正确地处理组件的创建插入或移动。

在渲染器层面,递归地渲染组件是一件很容易的事,但是需要重点处理好每一个组件的上下文信息,上下文信息极其重要,组件所需的渲染数据可能就来源于这些上下文信息而不只是数据中心,比如表格中的 行数据

自由布局在编辑器中的细节

为什么是数据中心

在架构图中,比较让人困惑的应该是数据中心和行为中心了,那数据中心是什么呢?

简单地讲,它就是一个响应式对象,组件渲染时需要用到的数据就从它里面取,向内输入的数据比如用户输入也存到它体内,当然行为需要的数据比如接口调用入参的来源也是它。

数据中心

白色的这个小图是我从我们系统中图片展示组件的配置中截出来的,它配置了图片展示数据的来源,来自数据中心的 row 对象的 cover 字段。数据中心通过链式字段名和视图以及行为的数据绑定发生关联。

左边这张黑色的大图是数据中心的简易实现,我们需要将数据中心打造成响应式以确保数据驱动页面能顺利进行。

为什么打造数据中心?因为通常我们页面渲染及其他数据是存放于页面状态或全局状态中的,当我们要对页面进行渲染以及逻辑处理时,就必须将数据的流转考虑进去。数据的主要来源是接口和用户输入,页面配置是静态的,接口和用户输入是运行时的,要将这两者有机关联,并且要求低耦合,比较好的方式就是将行为产生的接口数据送入数据中心,由组件自己拿取。

这样就做到了存数据和取数据两个动作的执行者相互是黑盒的,取数据的人并不知道数据是谁存进去的,存数据的人也并不知道我存的这份数据到底给谁用。因此,这种设计方式很好地实现了静态配置与运行时状态的有机结合。

行为中心是什么

我们总需要一个地方去控制数据中心的数据流转,数据中心没有数据来源也没有数据去向的话就是无用设计。就像我上文讲的,我们不仅要对页面结构进行可视化搭建,也需要对数据逻辑进行可视化搭建。行为中心就是让我们可以定义组件行为的地方。

行为中心

上图中大家可以看到左侧那个小图是我从按钮组件的配置中截出来的,意思就是按钮的点击事件绑定了名为「搜索」的行为。这张大图展示的就是行为编排时的界面,左侧是行为库,中间是行为编排画布,右侧是行为的配置。

有了行为中心后,我们对逻辑的控制就比较方便了,通过它我们能实现页面初始化的时候进行数据获取并展示、点击按钮时收集表单数据并请求接口等等。

在编辑器层面,行为中心的逻辑编排使用了 AntV G6 引擎进行渲染,输出的数据结构也是参照了 AntV G6 的输入数据结构。

在渲染器层面,行为中心在收到执行某个行为组的信号之后,会寻找这个行为组中的起始节点,然后根据起始节点的不同类型(接口请求、提示、比较等)执行不同的逻辑,执行完毕后会寻找节点的下一个关联节点继续执行,直到整条链路的逻辑执行完毕。

落地与实践

经过大约每个系统 3 月/人的开发,最终移动端搭建系统支持了 150+ 运营页面 99% 的搭建需求,管理后台搭建系统大约节省了 50% 的开发成本。

落地效果

不过我们的方案也有缺点,有不少东西需要约定俗成,虽然有文档辅助,但是免不了认知上有差异。并且由于系统稍稍有些庞大,所以第一次开发的成本会比较高,不过要先忍住痛,以后才能舒坦。

如果大家的团队也有尝试的想法,我强烈建议先思考它能否真正为团队带来价值,能否真正解决大部分痛点,再确保有可靠的人、充分的时间和完善的技术方案。

管理后台搭建系统截图

这是我们管理后台搭建系统工作台的截图,得益于自由布局、行为中心和数据中心的结合,各种形式的后台管理页面,比如列表页、表单页、详情页都能轻松支持。在后台管理系统中万变不离展示型组件和输入型组件。

截图中正在搭建的是后台管理系统的列表搜索页。列表页中的搜索条件区域其实就是个表单模块,各个输入组件将用户输入的数据送入数据中心,当点击搜索按钮的时候就由搜索行为从数据中心拿取用户输入并调用接口,接口调用成功后由接口行为将数据存入数据中心,数据中心的响应性使得页面中的表格部分发生同步的展示更新。

未来规划

目前我们还只进行到了低代码领域的初级阶段,还需要逐步迭代向零代码甚至智能化进发。

我们下一步的计划就是尽可能增加常用的模板组件与不同场景的页面模板以减少从头搭建页面的成本。此外我们将从实践中体验搭建系统的不足,尽可能提高它的自动化程度和组件库丰富度。

未来规划

参考

  1. 国内低代码平台从业者交流平台github.com/taowen/awes…
  2. h5-Dooringgithub.com/MrXujiang/h…
  3. GrapesJSgithub.com/artf/grapes…
  4. AntV G6g6.antv.vision/zh
  5. Ant Design 设计价值观ant-design.gitee.io/docs/spec/v…

更多精彩请关注我们的公众号「百瓶技术」,有不定期福利呦!

猜你喜欢

转载自juejin.im/post/7095676448555401223