在低代码开发中,除了基础组件与物料之外,模板也是必不可少的模块,是基于物料之上的更高级的产物,除了具备业务属性之外会更偏向专属的技术领域,例如可视化大屏、数据分析、中台管理等。
此外模板通常是比较完整的应用程序结构,可以快速创建一个具有基本功能的应用程序,并且可以根据需要进行修改和扩展,不再单单只有前端可见的内容,会与对应的业务绑定更深,比如电商、CRM、CMS 等。
本章节就来带各位同学一起学习低代码中模板的相关设计。
在设计低代码模板的时候,往往需要考虑以下几点:
对此,我们的模板中心需要具备如下的能力:
如使用物料平台来管理组件一样,我们也需要一个可视化的模板中心来统一管理各种丰富的模板库,包括不同领域行业能力的应用,如企业人事管理、物流管理、电商报表平台、意见收集、疫情管控等标准化的能力,提供可视化的能力方便用户使用。
如下原型图所示。在设计初期,模板中心大体上需要具备以下几个功能:
与常规的搭建不同的是,模板中心的使用者一般都是对开发并不熟悉的普通人,所以物料市场在开发的过程中一定要提供非常完善的功能,尽可能减少用户的理解与使用成本。
既然模板中心拥有能够管理示例模版的功能,那么理所应当的编辑器方面就需要在发布中开辟一条支线功能,那就是将当前的应用发布成为模板。
比如,公司销售员工小张需要做一个销售客户信息收集表,需要用户录入信息且进行数据管理。此时小张就使用平台搭建了一个简单的应用完成自己的工作。但是过了一段时间,小张的几个同事也有类似的需求,那么小张就可以将其发布为模板,他的同事就可以 Fork 当前模板到自己的编辑器下进行一些字段信息的修改和调整,从而快速满足自己需求的应用。
所以模板也可以看成更高级的复合物料,由当前领域的熟练工按照业务需求使用基础的物料配置一个模板,通过模板市场可以提供给不熟悉开发模式,或者对当前领域并不熟悉的人使用,如果熟悉淘宝装修的话,也可以理解一些设计功底好的运营配置好各种不同的营销店铺模板提供给小 B 商家使用。
尽管低代码平台可以大大减少应用程序开发的时间和成本,但基于 Schema 配置出来的功能一定是平台内置的且要保持最大程度的通用性,所以在一些特殊的情况下依旧需要进行一些二次开发,和一些相应的配置及逻辑的修改。
因此,低代码平台通常会提供运行时渲染和代码工程生成这两种产物结构,使得用户可以查看和编辑由平台生成的代码。这个机制可以是一个内置的代码编辑器,也可以是一种将代码导出为标准工程项目的功能。通过这种方式,用户可以在需要时查看和编辑代码,从而更好地控制他们的应用程序完成需求开发。
如果需要实现这种工程,我们就需要抽离出一套通用模板提供给出码生成器,将 Schema 中约定的协议注入到模板工程当中,最后不管是在线编码还是导出二开都由用户自己决定。
导出二开有一个非常严重的问题,就是产物很容易脱离原有的 Schema 架构。一旦脱离了 Schema 的架构,这个项目就很难再次使用低代码模式去迭代了,如果想长期迭代,最好还是在线编码,约束开发者的编码界限。
即使导出二开有上述弊端,依然有其存在的价值,基础的功能都可以通过低代码配置完毕,而且通过模板渲染出来 ProCode 产物,从代码风格、命名规范、安全性等来说都能达到较高的水准,给未来的项目迭代打一个好底子。
模板工程是指一种预先配置好的代码项目,它包含了一些基本的代码结构、依赖库、配置文件等内容。
在团队中,我们往往都会有自己的脚手架(CLI)工具,其中一定会具备通用项目的拉取和创建。
哪怕团队规模小,也不会完完全全从 0 到 1 去搭建一个新的项目,都是利用已经封装好的一些特定模板项目来直接开发。这就是我们常说的模板工程了。比如 Vite 在初始化项目时,可以通过 --template [template name]
来指定需要生成的项目类型,以此来生成一个开箱即用的环境。
通常情况下,一个模板工程会包含一些通用的功能和模块,例如路由、状态管理、主题等,开发者可以在这个基础上进行扩展和定制。在低代码平台中,整个模板工程的基础模块通常会取决于产品的协议和工程的设计,基于这个基础之上才能保证后续生成的项目工程具备一定的扩展能力和可用性。
开头就介绍了我们是通过Schema
的通用协议来生成代码的,那么如何将 Schema 协议输出成完整的代码文件呢?
此时就需要用到一个前端历史发展以来最常见的技术,也就是模板引擎。通过模板引擎定义好渲染规则来插入相应的内容,最后将其输出成为一系列的文件夹与文件,最后插入到模板工程当中,就可以进行打包下载了。
如果有同学做过通过 Swagger、OpenApi 等接口协议生成本地 Axios 接口和 TypeScript 的类型的同学获取就会比较清楚内部的一些实现逻辑:
如下示例所示: 这是我早期写过的一个接口生成器 tpl,它是基于 ArtTemplate 的规则来实现的,通过拉取 yapi 或者 Swagger 的相关 JSON Schema 解析,通过以下提前声明好的模板配置,传入相关的数据就可以生成对应的接口请求函数文件。
import request from '{{requestImportResolve}}'
const {{name}} = (allParams, options) => {
{{set isParams = params.length > 0}}
{{set isQuery = query.length > 0}}
{{if isQuery || isParams}}
const {
{{if isParams}}
{{ each params }}
{{$value}},
{{/each}}
{{/if}}
{{if isQuery}}
{{ each query }}
{{$value}},
{{/each}}
{{/if}}
...data
} = allParams
{{/if}}
return request(`{{path}}`, {
method: '{{method}}',
params: {
{{each query}}
{{$value}},
{{/each}}
},
data: {{isQuery || isParams ? 'data' : 'allParams'}}
})
}
export default {{name}}
当所有文件生成完毕后,就可以写入到本地目录。此时一个简单的接口代码生成器就完成了。
低代码平台的模板渲染也是一个道理,不过相比于生成接口请求而言,页面生成更加复杂,需要将国际化多语言、动态表达式、页面异步资源依赖、数据源等都做一个通用的生成处理。这里先简单做一个初步了解,后续在实现的时候会一步步去进行实现。
如下图所示,左侧是之前在协议篇提到过的基础协议结构,右侧则是模板工程的结构。在后面的实现过程中,会提供一个 @lgnition-lowcode/generate 包来完成以下 Schema 协议转换到模板工程的转换逻辑。
市面上有很多非常优质的模板引擎开源项目,已经获得了很多知名项目的认可。在这里我就简单列举一些我个人觉得不错的项目:
由于我们未来的模板生成具备一定的复杂度,所以最终这个产品的模板引擎将选择 Nunjucks,具体的开发介绍将在后续的文章中进行。
本章节主要讲了模版相关的设计与我们需要实现的模块。
通过以上功能,用户可以根据业务需求进行自定义和调整,同时将低代码平台的适用人群扩大,还降低了用户的学习与使用成本。
如果你有什么疑问或者更好的建议,欢迎在评论区提出。
7 架构:模板设计