低代码平台边界探索:多技术栈支持及高低代码混合开发
大厂技术 坚持周更 精选好文
作者 | 莫春辉
编辑 | 黎安
来源 | https://mp.weixin.qq.com/s/5h2K8ektFD1ZNilCxrRbXA
本文整理自华为云主任工程师莫春辉在 GMTC 全球大前端技术大会(深圳站)2021 的演讲《多技术栈及高低代码混合开发——华为云低代码平台架构探讨》。
当前,华为云部门内部的前端技术栈并不统一,比如华为云官网的 Console 控制台使用 Angular 技术栈开发,其他内部 IT 系统使 Vue 技术栈开发。因此,华为云要建设一套低代码搭建平台,对内提效能要同时兼顾 Angular 和 Vue 两种技术栈,对外建生态则要同时支持 Vue 和 React 技术栈。
另外,目前业界的低代码搭建平台大多局限于简单的应用开发,而华为云自身的业务逻辑中,既有需要用高代码开发的复杂页面,又存在一些简单页面。这些复杂页面,你很难完全通过可视化拖拽搭建出来,但对于简单的页面,又希望能够使用可视化拖拽快速生成。因此,支持高低代码混合开发的需求就摆在了我们的眼前。
华为云低代码平台建设背景与诉求
华为云低代码平台的建设背景
在 Gartner 的定义中,低代码平台被称为企业级低代码应用平台,是支持快速应用开发,使用陈述性、高级的编程抽象(如基于模型驱动和元数据编程语言)实现一站式应用部署、执行和管理的应用平台。不同于传统的应用平台,它支持用户界面、业务逻辑和数据服务的开发,并以牺牲跨平台的可移植性、应用开放性为代价来提高生产效率。
正因为牺牲了跨平台的可移植性和应用的开放性,各厂商开发的低代码平台,都不约而同地朝着“低”的方向走,越低越好,甚至是无代码、智能生成代码,于是就容易忽略“高”的需求,忽略与“高”的结合。而且,各厂商都希望用户从头到尾都在自己的平台上进行开发、全程托管,于是就容易忽略“被托”的需求,或者说“被集成”的需求,忽略与存量应用的结合。
这种忽略其实也是不得已而为之。如果不牺牲跨平台可移植性,就有可能支撑不同平台不同技术栈、生成可移植的代码,与现有的高代码(纯手写代码)相结合;如果不牺牲应用开放性,就有可能更好地支撑被集成的需求,灵活地与存量应用相结合。事实上,企业内部有非常多的存量应用,这些存量应用也想通过低代码平台去提升开发效率。
目前华为内部已经有几套低代码平台,华为云的低代码平台是否存在重复造轮子的嫌疑?2021 年 7 月北京的 GMTC 大会上,阿里巴巴研究员玉伯在谈前端现状的时候说到:阿里内部的低代码平台也很多,但深入到业务层面去看,你就会发现,那些“轮子”都是合理的,它确实是在解决特定领域的特定问题。华为云低代码平台的建设初衷,就是用来解决华为云领域内部的存量应用想通过低代码平台提升开发效率的问题。
如何在尽量不牺牲跨平台可移植性、尽量不牺牲应用开放性的情况下建设华为云低代码平台?这就是本文要探讨的问题。以下内容,我们将华为云领域存量应用的业务需求为线索,分析这些业务需求背后的实质问题,讨论用什么样的技术方案去应对这些问题,以及用什么样的平台架构去承载技术方案,最后讲讲建设过程中我们所踩过的坑。
华为云 CRM 系统的低代码需求分析
华为云内部有一个 CRM 客户关系管理系统,这个系统已经开发完成并且上线运行,属于存量应用。由于后面不断有新的需求,需要开发新的页面,而那些新的页面又跟原来的页面非常相似,所以重复性的开发工作比较多,于是 CRM 的开发人员就想利用低代码平台来搭建新页面。
由于新的页面跟原来的页面非常相似,CRM 的需求其实是想将原来的页面封装成可配置的页面模板。这样在面对新需求时,只需在低代码平台里配置一下页面模板就能产生新的页面,不用再重复开发。可配置的页面模板也是由 CRM 开发人员在低代码平台搭建而成,而产生的新页面则必须提供源代码,以便与 CRM 原系统一起编译构建,组成一个完整的应用,如下图所示:
左图是开发人员日常使用的 IDE(Visual Studio Code),低代码平台作为 IDE 的插件嵌入到 IDE 里。开发人员在平台里通过可视化方式搭建页面,保存页面的时候平台会生成页面的源代码(中图),与原来纯手写的代码一起编译生成应用(右图)。这里的可视化搭建相当于部分代替了原本需要手写代码的工作。
CRM 低代码需求背后的实质问题,其实是 ProCode 与 LowCode 的混合开发。ProCode 就是我们传统意义上的高代码开发,即所有代码都是纯手写的,而 LowCode 就是借助可视化工具搭建页面,只需编写少量代码。所谓的高低代码混合开发就是:在本地 IDE 里,有些场景直接手写代码,有些场景则用可视化工具搭建,生成代码到本地工程。混合开发的目的,仍然是想充分利用低代码平台的能力,提高开发阶段的生产效率。
华为云 DevOps 系统的低代码需求分析
再来看一下华为云另一个领域的低代码需求,这个需求来自 DevOps 系统。在 DevOps 流水线上,我们允许用户添加自定义的插件,这个插件能让用户干预构建和部署过程。
在使用插件前,需要通过一些页面来配置插件的参数,而这些页面当前是由 DevOps 团队开发。为了减轻团队的负担,他们希望借助低代码平台的能力,让用户在 DevOps 网站上直接搭建页面,页面保存后同样生成源代码,集成到 DevOps 系统里。这个需求与 CRM 不同之处有三点:
如果仅仅是生成不同技术栈的源码,相信很多低代码平台都能做到,但是我们面对的是不同技术栈的组件。比如一个按钮,CRM 是用 Angular 开发的,DevOps 是用 Vue 开发的。两个技术栈开发的按钮,它们的属性、方法、事件,甚至功能都不一定相同。打个比方,我们要给这个按钮设置颜色,Angular 的属性名称叫 type,属性的值是 success,而 Vue 的属性名称叫 color,属性的值是 green,两者并不匹配,如下图所示:
所以,用 Angular 组件搭建的页面,生成的 Vue 源码是跑不通的。有些人可能会说,通过 DSL 做属性映射,但是,如果功能不同,用 DSL 也无济于事。那么,我们是不是我们要为不同技术栈,不同领域打造不同的低代码平台呢?
如果这样做了,我们的成本会非常高,这个成本不仅包括软硬件资源的投入,还包括研发和运维的投入。而且各技术栈的低代码物料的不通用,还会造成物料生态的割裂。因此我们的低代码平台方案要能够支持不同的技术栈。
与传统 Visual Studio 可视化 IDE 的区别
把低代码平台嵌入到 IDE 里,通过可视化搭建生成源代码,这与 20 年前流行的 Delphi/ C++ Builder/ J Builder/ Visual Studio 非常类似,当然这些工具今天也还有人在用。
如下图所示的 Visual Studio,左边是可以拖拽的组件,中间上方是画布,左边的组件可以拖到画布里,中间下方是代码编辑区域,右边是文件系统以及组件的属性配置面板。可见,虽然技术在向前演进,但是解决问题的思路又回到了原点。
两者的相同点不难看出,都是可视化搭建,都会生成源代码。要厘清两者的区别,我们从以下三个维度去探讨:
让业务人员参与低代码平台开发
厘清两者的区别之后,有人可能会指出:为什么让业务人员参与混合开发,全部由专业编程人员不行吗?为什么要高低代码混合开发?把开发流程复杂化,增加学习成本。有些人甚至还指出:LowCode 是行业毒瘤,它没有任何未来,不值得我们任何的投资和想法。让不懂软件开发的人可以写代码,这个想法就是错的,而且错的非常离谱。我们从以下两个方面来回应这些问题和说法:
本文我们所讨论的华为云低代码平台,不同于市面上常见的低代码平台,它不仅仅可以实现简单的增删改查页面,还能支持复杂的 CRM 系统页面开发,还能生成 CRM 和 DevOps 不同技术栈的源代码,并与原 CRM 和 DevOps 系统编译集成。此外,它让不懂编程的业务人员,与专业的开发人员一起协同工作,每个人负责各自擅长的部分,使得低代码平台能够适应更多的业务场景,覆盖更多的行业领域,进一步拓展了低代码开发平台的边界。
支持多技术栈与高低代码混合开发
前面描述的 CRM 和 DevOps 系统的低代码需求,除了高低代码混合与支持多技术栈外,还有搭建复杂页面的场景。企业级的 CRM 客户关系管理系统,如果不能像 Salesforce 一样,把客户关系管理系统都做透,通过配置化实现客户侧的定制,那么低代码平台很难通过可视化搭建,构建复杂的 CRM 系统页面。这也是大多数低代码平台为什么只专注于简单的增删改查页面、或者流程审批电子流的原因。
然而这些问题如果没有解决,那代码混合开发就无从谈起。企业内部的存量应用,不会因为你做不到就简化页面,毕竟业务逻辑的复杂度本身就无法忽视。
如何可视化搭建复杂的 CRM 系统页面
这个问题我们给出的解决方案是:为用户提供自助搭建可复用区块的能力。
什么是区块?我们来看下面这张图,一个页面通常由多个区块拼接而成,每个区块由一到多个业务组件构成,每个业务组件都由基础组件实现。在低代码平台里,基础组件和业务组件都属于原子组件,即不可拆分的、平台内置的、可以拖到画布用于搭建区块的组件。一个复杂的页面通常可以拆分成若干个区块,而区块里面也可以嵌套区块。只要让用户能够复用已搭建好的区块,复杂的页面就像搭积木一样,一层层摞起来即可。
我们用低代码平台搭建的页面,会有一个描述页面信息的文件,这个文件我们称为页面 Schema。如下图左边所示,可以看到这个页面只包含两个组件,一个是 Button,另一个是 Input。如果我们认为这个页面可以复用,我们就把它转为区块,这时候该区块可以理解为:可配置的页面。所以只需在页面的 Schema 里面,增加区块可配置的属性,它就变成了描述区块的 Schema。如下图右边所示,该区块暴露了两个配置项:buttonSize 和 inputSize,分别对应页面包含的 Button 组件和 Input 组件的属性。
以下这张图展示了低代码区块的创建和消费过程。首先,从新建空白画布开始,用户在画布上拖拽组件、搭建区块,接着添加区块的业务逻辑。这里需要说明的是,我们提供了一些桥接方法,让用户可以调用高代码的部分功能,即前面提到的高低代码混合开发时,需要跟页面的其他纯手写的部分相互通讯、协调运行。第四步就是保存区块,让用户选择暴露的配置项,即将区块里所有组件的所有属性都罗列出来,让用户选择哪些属性可以对外暴露,以便复用的时候进行配置。第五步是发布区块到物料中心,这样下次新建页面的时候,用户就可以将这个区块拖到画布上,重复使用。
另外,由于我们的页面和区块都会生成源代码。如果两个页面都用到同一个区块,只是区块的配置有所不同,那么在生成这两个页面源码的同时,我们只会生成一份区块源码,然后让这两个页面都引用这个相同的区块。
如何在画布里展现不同技术栈的 UI 组件
目前大多数的低代码平台为了方便实现,都会限定画布只支持一种技术栈,甚至一套组件库。因为没有为用户提供页面源代码的需求,搭建出来的页面也不需要被其他系统集成,所以没必要考虑多技术栈,用一套组件库实现的成本是最低的。但是在华为云领域,面对 CRM 和 DevOps 的需求,我们要解决一个问题:如何在画布里展现不同技术栈的 UI 组件?这个问题我们给出的解决方案是——使用 Web Component 技术。
上图是 InfoQ 2020 年一季度,Web 开发相关的语言、标准、模式趋势图。可以看到 Web Component 处于中间位置,说明它已经到了主流成熟阶段,我们可以使用 Web Component 来解决跨技术栈问题。
目前三大主流前端框架:Angular、React、Vue 都已经提供官方的 Web Component 转换工具,我们利用这些转换工具,就可以轻松的将各技术栈的 UI 组件,全部包裹成 Web Component,然后当做 HTML 原生组件显示到画布上。需要指出的是,在生成的代码里,我们引用的仍然是原始的 UI 组件,而不是 Web Component,这是因为画布是设计态,源码是运行态,两者是不同的。
当前 Angular、React、Vue 是三大主流前端框架,未来又会出现什么样的框架代替它们呢?我们不得而知。但是,不管未来的前端框架如何变化,我们都先用 Web Component 技术收敛,再通过 DSL(Domain Specific Language)机制发散,生成不同框架不同技术栈的源码,这就是我们低代码平台的演进策略:
我们来举个 Vue 的例子说明 Web Component 方案。首先按照 Vue 官方的示例,定义一个 Vue 的组件,并注册成为 Web Component。然后在画布的 HTML 代码里,我们声明该 Web Component。假设这个 Vue 组件暴露的 options 属性,是数组类型。我们知道,在 HTML 标签上,attribute 属性只能设置为字符串或数值类型,因此,我们需要通过 JavaScript 脚本动态设置 options 的属性值。如下图所示:
接下来,我们将画布的 HTML 内容,用 AST 抽象语法树,解析成一个 JSON 对象,即描述页面的 Schema。从下面左侧的图可以看到,Web Component 组件的 options 属性,它仍然是数组类型。然后我们通过 DSL 将页面描述 Schema 转换成 Vue 的源码。从下面右侧的图可以看到,Vue 组件的 options 属性,也仍旧是数组类型。于是我们发现,从 Web Component 封装组件开始,到生成 Vue 的源码,整个过程中,给组件属性设置的值是可以透传的。
讲到这里,大家可能会有疑问,为什么不能在 Vue 应用中,直接使用 Web Component?以下列出 5 个理由,都摘自 Vue 的官网。简而言之,就是 Web Component 技术还不够强大,还不能完全替代现有的主流前端框架。
我们需要一个声明式的、高效的模板系统
我们需要一个有助于跨组件逻辑提取和重用的响应式状态管理系统
我们需要一个能在服务器端渲染组件并在客户端集成的高效方法
原生插槽没有 Vue 的作用域插槽提供的组件整合机制
隐式 DOM scoped CSS 的自定义元素需要将 CSS 嵌入到 JS 中
生成源代码 VS 运行时渲染
要将画布的描述生成不同技术栈的源码,需要借助 DSL 机制。我们知道,用可视化方式搭建页面,这个属于设计态。将页面描述文件通过 DSL 转换成源代码,然后编译成可以运行的应用,这个属于运行态。可以这么说,DSL 的作用就是将低代码从设计态转换成运行态。
但是,并不是所有低代码平台都会采用生成源码的方案。事实上,有很多低代码平台采用的是运行时渲染的方案,即将页面描述文件直接传给运行时解析引擎,然后动态地渲染页面。两种方案各有所长,这里列出四个对比项,如下图所示:
第一项,从性能上来看,运行时渲染要用到解析引擎,这个肯定不如生成源码编译跑的快;
第二项,由于运行时渲染一般要求所有应用都用统一的解析引擎,因此升级和修复平台问题时,只需针对统一的解析引擎,其效率自然要高于每个应用的源码都需要重新编译的方式;
第三项,DSL 生成源码天然具有很高的灵活性,只要用户通过自定义 DSL,就能生成任意想要的源码,因此扩展性和开放性要比运行时渲染高;
第四项,开发和运维的成本,两者应该相差不大。
低代码平台架构开发及生态建设思路
低代码平台架构设计
下图是我们低代码平台架构设计图。先看底部的平台服务,我们会利用华为云原生的能力搭建后端服务,会跟华为云的业务集成互通,比如跟我们的 Console 控制台业务集成等。中间这块是我们搭建平台的核心,底层能力提供搭建页面所需的基础组件、移动组件和业务组件,提供页面运行用到的逻辑编排、流程编排。
往上一层是我们用来粘合各个模块的平台协议,这个页面搭建协议是用来描述页面信息的,而组件描述协议是用来给组件设置属性的,物料资产协议是用来描述平台用到的组件、区块以及技术栈等信息,DSL 转换协议则是用来将页面或区块 Schema 转换成各技术栈的源代码。
低代码设计器是我们核心中的核心。首先从导入物料开始,中间是设计器的各个模块,这些模块会接入我们的平台扩展生态,包括设计器的插件生态,以及组件和区块生态。最后,设计器还要负责生成源代码,适配多终端多技术栈。再看上图右下角,我们为了实现设计开发一体化,会提供在线设计平台、提供支持高低代码混合开发的 VSCode 插件。
平台管理中心包含很多个中心,我们会先在物料中心挑选物料,然后打成物料资产包,再到平台中心选择刚打好的物料资产包,用来构建各领域的平台,接着在应用中心管理各领域平台生成的应用。PaaS 平台服务就是支撑我们去构建定制的平台,提供平台的运行时服务,另外还要支撑应用的设计、开发、构建、部署等。
有了 PaaS 平台之后,我们就可以提供 SaaS 能力,既可以开发传统的中后台应用,也开发华为云的 Console 控制台应用,甚至包括我们的 WeLink 移动端应用、鸿蒙的多端应用,然后再将这些应用发布到我们的应用生态市场。
低代码平台工作流程
下图是我们的低代码平台工作流程。先从底部的低代码后端说起,可以看到包含了前面说的物料中心、平台中心以及应用中心,这三个中心的后端都会连接一个数据中心,再由数据中心连接数据库。平台中心构建出来的产物是低代码平台实例,VSCode 模块根据模板工程把这个低代码平台实例打包编译,构建出一个 VSCode 插件。
物料中心会构建出两个产物,分别是物料资产包,以及搭建页面所需的组件库,它们会被低代码平台实例动态加载。每个平台实例都是由设计器各个模块组装而成,这些设计器的模块都来源于 npm 仓库。每个平台的实例都会请求对应的平台服务,平台服务提供各技术栈的页面预览功能,并且将生成的代码提交到 Git 库,再通过流水线发布应用。
低代码组件及区块构建流程
接下来我们看一下,物料中心的两个产物,物料资产包和组件库,它们是如何构建的。如下图所示,首先在物料中心的前端页面,我们点击构建组件和区块的按钮,后端服务就会分别执行构建动作。先看左边的组件构建流程,我们会根据用户选择的技术栈,安装相应的 Web Component 组件库,接着生成构建代码,代码里引入用户选择的组件,并且按照物料资产协议,输出该组件的描述信息,最后用 Rollup 打包构建,生成组件库。
再来看右边的区块构建流程,我们先从数据中心里获取区块的 Schema,然后将 Schema 转成区块的描述信息,所有区块的描述信息都会插入到 material.config 文件里,这个文件是按照物料资产协议进行整理,包含平台用到的组件、区块以及技术栈等信息,这个文件最后被打到物料资产包里,并且保存到数据中心。
低代码平台项目开发流程
下图我们低代码平台的项目开发流程。流程分三个角色,首先由项目经理在平台中心新建一个项目,然后设置可视化设计器的默认配置,比如设计器用什么样的主题,是深色还是浅色主题、设计器的面板有哪些插件、工具栏上有哪些按钮等。接着设置平台的默认配置,比如使用自定义的 DSL 配置、设置代码仓库的地址、监控应用所需的埋点信息等,下一步是设置项目所用的物料,比如用什么技术栈的组件、用什么领域的区块及模板。最后,项目经理点击构建平台的按钮,等平台生成后,就会通知开发人员登录平台网址,或者安装 VSCode 插件。
开发人员可以在平台上创建低码或无码应用。如果是低码应用,则可以创建分支,支持多人协作;如果是无码应用,只需选择模板,做一些简单的配置。经过一系列的迭代开发,用可视化工具搭建完页面,平台就可以通过 DSL 生成代码,最后用流水线部署应用。在开发过程中,如果发现组件缺失,还可以通过专业前端开发相应的组件,然后作为源码物料导入到物料中心。另外,由于用户也可以自行搭建可复用的区块,将区块作为低代码物料发布到物料中心,形成物料的双向流通。
低代码平台建设过程中踩过的坑
第一个坑是关于 Vue 的 Web Component 转换工具,我们使用 Vue3.2 版本推出的转换工具。当时发现一个问题,就是 Vue 组件转换成 Web Component 之后,使用 JavaScript 脚本设置它的 property 属性,只有第一次设置是生效的,后面再设置是无效的,请注意:这不是 HTML 标签上的 attribute 属性。什么原因呢?
我分析了一下 Vue 的源代码,原来转换后的 Web Component 只在初始化时读取 property 属性,后面并没有监听 property 属性的变化。但是低代码平台就是要对画布上的组件进行属性设置。
于是我就对转换工具做了点改进,给转换后的 Web Component 添加了一个方法,把要设置的属性传进去,然后调用它内部的 render 方法重新渲染组件,这样设置就生效了。值得一提的是,我发现 Angular 的 Web Component 转换工具并没有这个问题。
第二个坑是关于 VSCode 插件,我们是通过 VSCode 插件来实现高低代码混合开发的需求,如下图所示。
首先把低代码平台解耦,然后通过 VSCode 的 WebView 嵌入这个低代码平台。接着我们就发现,平台通过 WebView 发送网络请求的时候,是不能携带 Cookie 的,这样就导致我们的低代码平台无法进行鉴权。
我从 VSCode 的 Github 上搜到这个问题的官方回复,他们是这么说的,WebView 没有 host 主机的概念,它只是在渲染一个 HTML 文档,并不是你想要访问的网页,所以不会有 Cookie 和 LocalStorage 的概念。那我们该怎么办?
由于 VSCode 它本身自带 Node.js 客户端,于是我们就想到,把这个 Node.js 客户端当做代理服务器,转发 WebView 的请求。当后端服务返回生成的源代码后,再借助 Node.js 客户端将源代码写入到本地工程。这样,就实现了高低代码混合开发的基本功能。最后我们还需要在 VSCode 里,实现内置的账号登录功能,这样才能让请求带上 Cookie,完成整个平台的鉴权。
低代码平台的相关问答
以下问答系演讲结束后根据听众的反馈整理的,选取一些有代表性的问答分享给大家:
总结和展望
华为云的低代码平台要想持续发展,就需要建设物料生态、平台生态以及应用生态。只有物料的双向流通才能促进物料生态的发展,除了组件、区块之外,我们还要为用户提供自助搭建可复用模板的能力,进一步丰富物料的生态。我们要做低代码的 PaaS 平台,利用 Web Component 技术以及 DSL 机制,为不同领域,比如办公、零售、制造等,去创建定制的平台。不仅要能够生成桌面端应用、移动端应用,还要能够生成鸿蒙的多端应用,扩展我们的应用生态。
低代码的物料生态、平台生态、应用生态,这三者不是互相孤立的,而是相辅相成的。我们要把这三个生态圈打通,形成合力,这样下面这张图,就不是三个圈,而是三个环环相扣的 8。
据 Gartner 预计,到 2024 年,低代码应用开发将占应用开发总数的 65% 以上,将有 3/4 的大型企业会使用至少 4 个低代码平台进行 IT 应用开发。
另外,据不完全统计,目前国内外大大小小的低代码厂商至少有 60 个以上,而且大厂商内部的低代码平台可能还不止一个。作为企业数字化转型的工具引擎之一,低代码平台必然会被越来越多的企业所了解并加以使用,使用的场景也会越来越丰富。我们在开发或使用低代码平台时,要清楚低代码不能一蹴而就,而要持续迭代、持续演进,要不断探索和拓展低代码开发平台的边界。
❤️ H5-Dooring,让H5制作更简单
目前H5-Dooring架构升级, 已支持多种搭建布局模式, 如网格布局, 自由布局, 可以一键切换布局模式:
欢迎体验: http://h5.dooring.cn/h5_plus
❤️ 谢谢支持
以上便是本次分享的全部内容,希望对你有所帮助^_^
喜欢的话别忘了 分享、点赞、收藏 三连哦~。
欢迎关注公众号 趣谈前端 收获前端一手好文章~
标签:
相关文章
-
无相关信息