git 仓库地址 前言:
最近把go micro 微服务突破了,非常开心。前面有些 go micro 相关文章,大家有兴趣可以看看,基于Golang的微服务——Micro实践(一)接下来会尝试写一个完整的微服务项目,这个跟本文要说的无关。
本文主题
除了go micro 微服务,最近一直在做 前端可视化编辑工具,中秋放假,才爬起来,还是写点文章让假期更有意义吧。文章里可能不会涉及到太多的源码,毕竟是公司项目,没法分享。但是可以跟大家一起讨论下实现思路,想到哪里说哪里了。欢迎大家留言讨论。
一、可视化编辑工具定位
技术栈:React.js + Node.js (目前 Vue版本的我也初步实现了...有种感觉,最终想把这样的可视化编辑工具做到好用要深入到AST 抽象语法树。)
这里说下我这篇文章里描述的可视化编辑工具的定位:面向初级前端开发者和后端人员通过拖拽和配置快速生成前端页面,搭建项目。
刚开始接到这个需求时是一脸懵逼的,感觉也没有太多的例子可以参考。后来做技术方案和调研的时候发现其实有很多前辈和先烈在做可视化编辑工具。相比大厂或者先烈们都在考虑如何通过这样的开发工具提高开发效率吧。 其实我们的初衷也是为了搭建一个快速开发平台,实现一个项目的快速开发,尽量少写代码。在调研的过程中收集了很多资料。文章中也会列举一些让我受启发的。
二、如何提高开发效率?
平时很多人应该做的是堆码的工作,很多重复性的东西做久了厌倦了,于是大家都想着提高效率。很多大厂都在研发跟提效相关的工具,其中可视化编辑工具是一个很大的趋势,据我调研,阿里的云凤蝶在一两个月前将 云凤蝶移动端建站功能 准备切换成中台的快速开发平台。那这个定位基本就跟我们设想的可视化编辑工具耦合了,我们做的时候一个大的设想也是,可以借助可视化编辑工具快速生成一个简易中台,节省开发成本和周期。
我们做工具的目的是提高开发效率,那如何才能提高效率?大家可以参考下这篇文章,我觉得总结的很到位 减少代码量的 7~8 种方式。
我自己根据这些文章也简化罗列几点(这里偷懒,把之前总结的文档直接截图了):
大致的解释下里面涉及到的点:
脚手架:
跟我们日常用到的 vue-cli create-react-app 类似,用命令行的方式快速初始化一个项目,我们的设想是这个CLI 工具可以帮助我们快速初始化一个复合我们规范的项目架构和相关依赖。工具发布到npm仓库,使用者可以全局下载,然后用命令行方式使用,这样可以避免使用者自己一步步的新建项目,也可以实现项目初始化时是一个标准的流程。也可以通过特定的命令快速生成文件到某一个目录或生成多个文件到相关联目录,如果您用过 Laravel tinker.就会这种方式是多么便捷了。当然也可以参考Angular CLI ,它的那一套CLI工具在前端三剑客里算是做的最强大了。自然就可以提高效率。
工程化
做一套项目规范,这种规范不会是细化到变量函数定位规则等,更多的是大规范,保证标准化输出。
编辑器插件
比喻开发Vscode 插件,针对我们自己的规则和项目结构做代码自动生成
组件设计系统
比如 storybook ,集成了组件开发,预览,调试和文档说明的一整套方案,组件代码可以直接复制使用,方便我们快速系统的研发组件。
减少代码量
这一点就是综合行的了,总的来说,减少手写代码量就是效率的提升。
物料资源
可以把封装过的组件和区块(区块这个概念大家可以比照antd-design 那一套来看,我也是受它的启发),把页面级别的区块当作一种资源,这种资源可以做版本维护和修改。下次需要使用的时候直接拿来用就好了。上传的图片也可以作为一种资源池,需要的时候直接在资源池里选取就好了,不用多次重复上传。
可视化编辑器工具
也就是本文的重点了。通过预置组件,然后拖拽快速生成页面布局,继续拖入组件丰富页面,然后编辑器工具读取组件的 props 配置信息,用可视化配置的方式配置组件的 props ,使用者可以预览组件,最后下载保存代码,在浏览器端就可以生成 file.jsx 代码文件,通过浏览器下载,整个过程不需要后端参与。
编辑器工具
业务架构
用两张图来描述整体的业务架构
这里面会涉及到几个概念,组件,插件,区块,模板,具体解释图上也都有备注,强调一点的是这些统称为物料资源,为的就是代码复用,减少代码量。
编辑器配置原理
还是用图来说明吧
这张图是上文提到的组件 props 配置的原理图。当某一个预置组件被拖入到主操作区的时候,点选当前组件对象,组件的props 配置信息会通过 不同值类型的表单组件展示出来。例如:String 类型就用 Input 组件展示, Boolean 值用 Switch 组件展示。配置表单组件具体是哪种是由需要配置的值类型决定的。
编辑器总体技术架构
还是上图
分析下这张图:首先看整体,形成的是一个闭环,也就是我们整个可视化编辑工具和配套的CLI 工具等等提升开发效率的配套设施是可以循环往复,不断迭代具有生命力的。再从右下角看,我们一系列工具最终生成的是一个完整的项目,项目是由CLI 命令行初始化后,然后由一个个组件构成的,这些组件聚合生成区块,也就是页面级别的组件,再通过拖拽的方式,将组件拖拽到编辑器的主操作区,形成组件数据树形结构,编辑器通过拖拽构造一套组件树对象,拖拽的时候其实修改的是组件树的json结构。通过修改数据,然后驱动页面的即时更新,这一块交给React 去完成就好了,我们只需要用json 数据树描述好组件树和组件配置 props 以及组件之间的层级关系就好了。编辑器输出的是json 数据,然后通过解析引擎将jOSN 对象编译还原成组件。生成一个大的组件树,通过 react 模板文件,最后生成一个 file.jsx 的react 文件,这个文件放入到 umi.js 的pages 目录就可以直接访问了。你可以把这个文件理解为我们日常写的react组件或页面文件。
下面用更具体的图来说明下项目里涉及到的几个概念:
组件
这个图片描述了更具体的组件概念,是系统里的最小资源级别,其他的大区块都是基于和这个构建的。
区块
区块是页面级别的,可以通过代码库实现版本维护,具体可以参照 antd-design 的区块来理解。图片中右侧的图示就是 整个区块的生命周期逻辑。
模板
模板可以理解为一个主题,项目初始化的时候会选择一个主体色,主体布局等。主题也是可以做版本维护的。
编译
这里说的编译还是最基础的编辑,暂时没有深入到 AST抽象语法树和,编译是代码自动生成的原理支撑。个人觉得,想要把可视化编辑器工具做好,后期必须得深入到 AST 编译层面。
可视化配置
- 可视化拖拽 + 即时编译预览
- 拖拽映射到HTML树形结构->AST->生成代码
- 可视化生成块,解析后生成的代码可以复制
- 后期实现生成的代码直接生成或者修改源文件
- 拖拽生成文件时可以选择目标目录
配置的方式不仅仅只有 props 一种,下面列举下我想到的
- config.json + JSON-Schema
- Template
- Props
- States
- Service存储
- LocalStorage存储
数据驱动
数据驱动是你一定要做好的思维转化,你拖拽操作最终映射的是数据结构的变化,将数据交给react vue 这样的框架,让框架去做UI渲染,整个工具开发过程中,深刻的体会到了自己的短板,深层次的数据结构和算法。大家一定要重视这两方面的能力哦。用一张图来形容数据驱动。
Node.js 服务支撑
- 浏览器没法操作文件,用Node.js做浏览器功能拓展
- 服务端支撑,操作文件和读取系统信息
- Node操作文件流,CLI命令行的底层支撑和核心
目前整个编辑器的实现没有用到 node 做拓展,但是综上所述,浏览器在操作文件这一块是存在问题的,后期需要引如 node 做浏览器的功能拓展
CLI 工具可以有哪些功能?
- 命令行脚本
- 快速查创建项目(可交互式选择布局)/ git clone
- 快速创建块
- 快速创建文件( 数据+模板=文件 ),路由随之生成
- 项目快速发布脚本
- 底层支撑就是Node
- 可参照Angular CLI
即时编译预览
这里用一张图描述了 rect 是怎么实现热更新和即时预览功能的
目前在做可视化编辑相关项目的有很多,但是真正好用的几乎没有。 阿里的氚云,内部项目 金蝉,对外项目云凤蝶等。但是这个方向的确是一个大的趋势,我总结了一个这个方向的未来展望:
最终应该会发展到 AI 编程和无代码。
存在的问题:
暂时无法解决自动生成数据流和业务逻辑。虽然生成了 react 文件,但是在数据流自动生成和 业务逻辑自动生成遇到很大的障碍,如果朋友们有好的解决办法,有兴趣可以评论留言一起讨论下。这里只能贴一些技术架构和原理了,具体代码展示没法展示出来。
文中一直提到我们,其实这个项目就是我一个人在做,非常吃力,需要考虑的配套设施和技术攻关的太多了,不是很容易快速的看到成绩...目前除了遇到的数据流自动生成问题外,其他的基本用实际代码论证了方案的可行性,也有一个可以生成 react.jsx 文件的编辑器雏形。
目前也有一些类似的工具开源了,但是我做的工具跟大部分的都有一个区别就是我输出的是 react.jsx 文件,很多工具输出的是 渲染后的页面。
相关概念
程序=数据+算法
要做到无码, 就必须有数据和算法
参考例子
在技术方案调研过程中找到了一些比较好的原理分析和代码实现,在这里给大家贴一下
推荐网易云从AST实现的---- 2023年10月16日更新
上面这个是新鲜出炉的,看作者是国庆最后一天发布的
点石 这个刚开始的时候官网看着很粗躁,貌似挣钱了?
上面的文章作者好像挺牛逼的
上面这个智能表单思路可以解决 组件可视化配置表单的问题
阿里的内部好像还有一个 【金蝉】
上面的无代码编程原理架构图很形象
附加
云凤蝶的2.0规划跟我想要实现的设想太像了,当然我也是参考了很多 ice飞冰项目思想。可惜云凤蝶还没开源,不然可以节约我们很多踩坑的时间,哈哈哈...,看下面👇的文章 云凤蝶可视化搭建的推导与实现
国外的
掘金没有栏目分组功能还是我没发现? 放一个 可视化拖拽里的一个知识点:
<!DOCTYPE html>
<html>
<head>
<title>拖拽测试</title>
<style type="text/css">
#target{
height: 160px;
width: 200px;
border:1px solid #000;
position: relative;
}
.dot{
position: absolute;
width: 10px;
height: 10px;
border: 1px solid pink;
border-radius: 50%;
background: #fff;
}
.left{
top:50%;
left: -6px;
transform: translateY(-50%);
cursor: w-resize;
}
.top{
top:-6px;
left: 50%;
transform: translateX(-50%);
cursor: n-resize;
}
.right{
top:50%;
right: -6px;
transform: translateY(-50%);
cursor: e-resize;
}
.bottom{
left:50%;
bottom:-6px;
transform: translateX(-50%);
cursor: s-resize;
}
</style>
</head>
<body>
<div id="target"></div>
<script type="text/javascript">
window.onload = function () {
var startX, startY, moveX, moveY, status, width, height, direction
var target = document.getElementById('target')
var arr = ['top', 'left', 'right', 'bottom']
var len = arr.length
for(var i = 0; i < len; i++){
var div = document.createElement("div")
div.classList.add("dot", arr[i])
div.dataset.direction = arr[i]
target.appendChild(div)
div.addEventListener("mousedown", function(event){
event.stopPropagation()
startX = event.clientX
startY = event.clientY
width = target.offsetWidth
height = target.offsetHeight
direction = event.target.dataset.direction
status = true
})
}
document.addEventListener("mousemove", function(event){
event.stopPropagation()
if(status){
moveX = event.clientX - startX
moveY = event.clientY - startY
switch (direction) {
case 'top':
target.style.height = height + moveY + 'px'
break;
case 'right':
target.style.width = width + moveX + 'px'
break;
case 'bottom':
target.style.height = height + moveY + 'px'
break;
case 'left':
target.style.width = width + moveX + 'px'
break;
}
}
})
document.addEventListener("mouseup", function(event){
event.stopPropagation()
status = false
})
}
</script>
</body>
</html>
实现元素 拖拽式修改 元素的宽高。示例里面的元素不是绝对定位的,所以请忽略(左,上两个拖拽指示按钮),实现了元素的左右,上下 改变宽高的功能。
放一下 React版本示例代码:ASTX,一直没时间维护....不过可以参考下原理,低代码可视化编辑器是很好的方向