AboutFE icon indicating copy to clipboard operation
AboutFE copied to clipboard

58、低代码

Open CodingMeUp opened this issue 2 years ago • 0 comments

最终场景: 基于模型设计直接生产标准化页面 低代码引擎的几大核心能力:入料、编排、渲染、出码

低代码引擎: 制定统一底层协议,基于标准打造出低代码平台的基础能力,并在此基础上提供定制化能力

架构分层

协议栈 --(实现)--> 低代码引擎 -- (扩展) --> 引擎的生态(包含 插件物料工具链面板配置) --(支撑)--> 低代码平台(宜搭 纪元 表单平台 数据平台)

前端技术领域

  1. 组件体系: 将页面中所使用的的元素进行原子化封装,通过配置选项让组件具备适应性调整的能 力
  2. 可视化搭建设计器:布局可视化、配置可视化、样式可视化
  3. 弱工程化:将打包、发布等等各种环节进行弱化,用户只需要所见即所得的关注页面产出

协议先行

  1. 低代码引擎物料规范
  2. 低代码引擎搭建协议规范

低代码入料

入料模块负责物料接入,通过自动扫描、解析源码组件,产出一份符合《中后台低代码组件描述协议》的 JSON Schema。这份 Schema 包含基础信息和属性描述信息部分,低代码引擎会基于它们 在运行时自动生成一份 configure 配置,用作设置面板展示

大体分为本地化、扫描、解析(【静态】: react-docgen解析JS/TS,自定义了 resolver 及 handler,前者用于寻找组件 定义,后者用于解析 propTypes、defaultProps,【动态】:require 组件进来 parse-prop-types 库,动态解析可以解析出全部的类型信息,因为 PropTypes 有可能引入依赖组件的一些 类型定义,这在静态解析中很难做到,或者成本较高,而对于动态解析来说,都由运行时完成了)、转换、校验 5 部分

低代码编排

编排,即将设计器中的所有物料,进行布局设置、组件设置、交互设置(JS 编写/逻辑编排)后, 形成符合业务诉求的 schema 描述 。本质是生产符合《低代码引擎搭建协议规范》的数据,在这个场景里,协议是通过 JSON 来 承载的,编排实际上操作 schema,但是实际代码运行的过程中,我们将 schema 分成了很多层,通过将 schema 和常用的操作等结合起来,最终将低代码引擎的模型分为节点模型、属性模型、 文档模型和项目模型。

  1. 项目模型(Project)

提供项目管理能力。通常一个引擎启动会默认创建一个 Project 实例,有且只有一个。项 目模型实例下可以持有多个文档模型的实例,而当前处于设计器设计状态的文档模型,我们将其添 加 active 标识,一个 Project 包含若干个 DocumentModel 实例,即项目模型和文档模型的关系是 1 对 n

  1. 文档模型(DocumentModel)

文档模型提供文档管理的能力,每一个页面即一个文档流,对应一个文档模型。文档模型包含了一 组 Node 组成的一颗树,类似于 DOM。我们可以通过文档模型来操作 Node 树,来达到管理文 档模型的能力。每一个文档模型对应多个 Node,但是根 Node 只有一个,即 rootNode 和 nodes。

  1. 节点模型(Node)

Node 节点模型就是负责这一层级的 Schema 管理。它的功能聚焦于单层级的 schema 相关操作 Node 节点模型核心功能点有三个: 1)Props 管理:通过 Props 实例管理所有的 Prop,包括新增、设置、删除等 Prop 相关操作。 2)Node 管理:管理 Node 树的关系,修改当前 Node 节点或者 Node 子节点等。 3)Schema 管理:可以通过 Node 获取当前层级的 Schema 描述协议内容,并且也可以修改它。 通过 Node 这一层级,对 Props、Node 树和 Schema 的管理粒度控制到最低,这样扩展性也就 更强。

  1. 属性模型(Prop)

一个 Props 对应多个 Prop,每一个 Prop 对应 schema 的 props 下的一个字段。 Props 管理的是 Node 节点模型中的 props 字段下的内容。而 Prop 管理的是 props 下的每一 个 key 的内容

项目、文档、节点和属性模型关系 整体来看,一个 Project 包含若干个 DocumentModel 实例,每个 DocumentModel 包含一组 Node 构成一颗树(类似 DOM 树),每个 Node 通过 Props 实例管理所有 Prop。整体的关系 图如下。

节点 & 属性模型是引擎基石,几乎贯穿所有模块,相信从上面的类图已经能看出几个基础类的职责 以及依赖关系。 节点 & 属性模型等价于 JSON 数据结构,而编排的本质是产出 JSON 数据结构,现在可以重新 表述为编排的本质是操作节点 & 属性模型了。

低代码渲染

低代码渲染的载体大多数都是在 Web 浏览器上。 所以低代码渲染是在 Web 渲染的基础上进行的另一个渲染黑盒。低代码渲染的模型是基于标准的《低代码引擎搭建协议规范》产出的 Schema。而影像是同 Web 端一样的网页,由于其特性,它可以只作为网页的一部分存在,也就是区块;它也可以作为一整个应 用存在,即应用级别的渲染

由于低代码渲染实际上底层是利用的 web 端渲染能力,即最终我们的语言都会转化为 web 端的 语言。所以这一个过程需要进行转化。而像是大多数编译器一样,低代码渲染的编译模式也分为预 先编译(AOT)或运行时编译(JIT)形式工作

运行时编译渲染(JIT)

运行时编译渲染又称为实时渲染。指的是,保留原始的描述模型,在网页加载并执行 JS 的时候,通 过递归、计算 props、设置上下文等实时操作来完成渲染的过程

JIT优势:

  1. 实时性强 运行时渲染是有其优势的,它省略掉了编译的时间,做到实时生效。对于低代码搭建的产 品来说,进行了修改之后是不希望在 1-2 min 甚至更长的时间才能在页面中看到效果,而是希望 在修改之后的下一秒就可以看到变更的效果。因为,大多数低代码的渲染都是选择这一方式,或者 就是 JIT 和 AOT 的渲染能力都能提供。
  2. 轻量化 现代化的前端项目基本上都没办法离开工程化体系,一个 React 项目至少需要 Webpac k、Babel、发布、部署等步骤。而对于运行时框架,我们需要的就只有 Schema 和一份前端渲染所 需的 SDK。对于运营、产品、后端等低代码使用人员是十分友好的。

JIT局限点:

  1. 性能瓶颈,和大多数的 JIT 的框架一样,JIT 渲染由于需要运行时进行编译,这个编译是会带来性 能损耗的。一方面是首屏时间时间的损耗。另外一方面在交互的过程中,由于上下文的改变,需要重 新进行递归计算,这个带来的损耗影响是更大的,因为这个会在首屏渲染出来之后,还会有操作卡 顿、延迟等问题。
  2. 小程序不支持,部分平台不支持 JIT,原生小程序不支持动态化渲染。小程序作为移动端上实现快速迭代、提升用户 体验、集成端能力的集大成的解决方案,已经成为商业的重要技术基础设施。而原生小程序有着诸 多的限制,它不能够直接操作 DOM,所以导致动态化渲染无法在该平台上完成。

预先编译渲染(AOT)

预先编译渲染又称为出码渲染,指的是,将 Schema 等模型通过编译器编译为特定语言的代码。预先编译渲染,我们在低代码领域叫做出码。如出码成 React,这样就可以省略 掉运行时编译的递归和计算流程,能进一步提升其性能。如果想完全抛弃运行时相关的代码,也可以直接出码为 JavaScript + HTML。

AOT优势: 性能优化上限更高,不能说 AOT 性能就会比运行时性能好,毕竟这很大程度依赖于出码之后的代码,如果出码之后是没有性能优化的,那么它的性能很可能低于运行时。但是由于其出码的形式是 没有受到限制的,所以它的性能是可以比运行时的性能优化的更好的。

AOT局限点:

  1. 成本高,由于 AOT 出码不是统一的,所以需要出码到不同的模型都需要写一份,所以出码的成本 相对比较高。
  2. 实时性低,出码需要较长的编译时间,所以在搭建页面修改之后,无法即时生效。所以无法使用在低 代码预览场景。

低代码出码

所谓出码,即将低代码编排出的 schema 进行解析并转换成最终可执行的代码的过程。出码是为了更高效的运行和更灵活地定制渲染。相对而言,基于 Schema 运行进行渲染的优点在于 其能实时响应内容的变化和接入成本低,而缺点是实时解析运行的性能开销和包大小都比较大,时 无法自由地进行扩展二次开发,功能自由度受到一定程度限制。

出码也会存在一些限制:一方面需要额外的接入成本,另一方面通常需要额外的生成代码和 打包构建的时间,难以做到基于 Schema 的运行时渲染那样保存即预览的效果。 所以不是所有场景都建议做出码,一般来说以下 3 个场景可以考虑使用出码进行优化

  • 场景一:想要极致的页面打开速度,降低 LCP/FID 这种场景比较常见的是 C 端应用,比如手淘上的页面和手机钉钉上的页面,要求能够尽快得响应用 户操作,不要出现卡死的情况。当一个流入协议大小比较大的时候,前端进行解析时的开销也比较 大。如果能把这部分负担转移到编译时去完成的话,前端依赖包大小就会减少许多。从而也提升了 加载速度,降低了带宽消耗。页面越简单,这其中的 gap 就会越明显。

  • 场景二:老项目 + 新需求,用搭建方式产出页面 这是一个很常见的场景,毕竟迁移或者重构都是有一个过程的,阿里的业务都是一边跑一边换发动 机。在这种场景中,我们不可能要求使用运行时方案来做实现,因为运行时是一个项目级别的能力, 最好是项目中统一使用他这一种方式,保证体验的一致性与连贯性。所以我们可以只在低代码平台 上搭建新的业务页面,然后通过出码模块导出这些页面的源码,连同一些全局依赖模块,一起 Merge 到老项目中。完成开发体验的优化。

  • 场景三:协议不能描述部分代码逻辑(协议功能不足或特别定制化的逻辑) 当我们发现一些逻辑诉求不能在目前协议中很好地表达的时候,这其实是项目复杂度较高的一个信 号。比较好的方式就是将低代码研发和源码研发结合起来。这种模式下最大的诉求点之一就是,需 要将搭建的内容输出为可读性和确定性都比较良好的代码模块。这也就是出码模块需要支持好的使 用场景了。

CodingMeUp avatar Apr 07 '22 03:04 CodingMeUp