Flutter低代码-Fair云开发平台实践

前言

Fair-Online 是面向Flutter 开发者,提供从Flutter 在线开发,到实时编译预览,打包发布、动态下发端侧更新,实现Flutter 线上动态化的一体化云开发平台。开发者无需配置Flutter 开发环境,在线开发调试代码,即时编译预览,所见即所得,结合58开源团队打造的Flutter 动态化框架 Fair 及热更新平台 FairPushy ,实现Flutter 线上动态化。

目前Fair 云开发平台已在Github 开源: Fair-Online Github 在线体验地址: Fair-Online Platform

Flutter 低代码

熟悉Flutter 的小伙伴应该都了解过 FlutterFlow ,它是目前比较完善的Flutter 低代码平台,面向的是Flutter 零基础开发者。开发者无需了解Flutter 的控件体系及语法规则,只需使用平台提供的微件和复合组件,拖拽生成页面即可。对于业务逻辑处理,比如网络请求、事件Action处理等,是通过可视化的属性编辑完成,平台会根据开发者的操作生成对应的Flutter 代码。

在体验使用FlutterFlow 的过程中,我们也发现一些问题。首先,对于页面UI开发,如果要实现一个功能复杂,页面层级较多的UI,使用拖拽组合,会变得非常繁琐困难,这对Flutter 开发者是不够友好的开发方式;其次,对于复杂业务逻辑的处理,比如网络请求,事件Action处理等,使用可视化属性设置,开发也比较繁琐,且学习成本较高。

所以,针对上述问题,在技术选型上,区别于FlutterFlow 等低代码平台的拖拽编辑实现,Fair-Online 是面向Flutter 开发者,提供在线代码编辑器,辅助以可视化的工程、页面、组件创建、编辑,以实现Fair 开发提效,且几乎没有额外的学习成本。为了方便不熟悉Fair 的小伙伴快速上手Fair 开发,平台提供了常用的工程、组件模板以及网络请求等业务逻辑,开发者在创建工程、页面时可选择模板创建,然后二次编辑。

Fair-Online 架构

整体架构设计分为前后端,都基于Dart 技术栈实现。 上半部分是前端,应用展示层。技术栈使用的是Flutter Web + JS。

中间服务层

  • 包括 Code Editor(代码编辑器)和 Preview(预览)等组件。
  • Code Editor(代码编辑器)是核心基础功能。其中视图部分使用CodeMirror , 它是一个使用JS实现的文本编辑器三方库;而逻辑部分,比如代码分析、语法检测、代码补全等,使用Flutter 实现。
  • Preview(预览功能),是基于Flutter 和Fair SDK 实现。

上层应用层

  • 包括Flutter/Fair 的编译运行,Fair 一键打包、代码导出、手机扫码预览等;以及工程、页面等编辑功能。

下半部分是后端,服务层,技术栈使用的是Dart Server。

中间服务层

  • 主要包括Fair SDK,Fair 语法检测插件。语法检测是Fair-Online 的重点及实现难点,后文会有详细介绍。

上层应用层

  • 主要包含用户工程相关,管理着用户的工程、页面、组件库等。

下面详细介绍下Fair-Online 中核心功能的实现。

在线代码编辑器

Flutter在Web上运行原理

Flutter Web 在Framework 层和移动端Flutter 是相同的,区别在于渲染底层,移动端通过内置skia 引擎调用GPU 进行绘制,而Flutter Web 则是将绘制引擎部分替换为标准HTML 标签以及Canvas 绘制的自定义标签,最终生成可绘制的dom 树。

依托于dart compile 工具的 js模块 (老版本为dart2js 工具),Flutter Web 的构建工具可以将中间产物 app.dill 进行读取和解析,并注入 Math、List、Map 等 JS 工具方法,最终生产出Web 平台所能执行的JS 文件。

Flutter Web与JS的互操作性

Flutter 在移动端的生态丰富,但是在Web 上面就差了很多,目前的Flutter Web 在开发中很大程度上依赖了Web 上丰富的三方库,所以能够与JS 的函数互相调用是很重要的能力。

不同于Flutter 在移动端上面与webview 的交互方式,由于Flutter Web 是运行在浏览器环境中的,并且本身Dart 也会经dart2js 转化为JS 代码,所以在Flutter Web 上面通过dart:js 或是packages:js 可以很轻松实现Dart 和JS 互相调用。

技术选型-CodeMirror

对于代码编辑器的选择上其实没有什么挑选的空间,首先Flutter 技术栈的三方库以移动端为主,所以想要接入代码编辑器这种组件,我们只能从JS 的技术栈上面选择。CodeMirror 是一款在Web 上面老牌的代码编辑器,功能强大,提供了十分丰富的API,并带有多种语言模式和插件,可实现更高级的编辑功能,完全可以满足我们的需求。

依赖Flutter Web 与JS 强大的互操作性,我们可以轻易地在集成CodeMirror,而Google 官方也提供了CodeMirror 的Dart 封装库,其核心实现就是通过dart:js 库对JS 侧的CodeMirror 进行API 的调用和交互 。

CodeMirror 作为Web 上面的UI 库需要基于html 标签来展示,而在Flutter Web 中需要借助HtmlElementView 来往Widget 层次结构中嵌入一个 HTML 元素(在移动端需要使用flutter_webview 插件),动态构建Html 标签需要在platformViewRegistry 注册后使用。


/// 构造用于承载CodeMirror的Html标签并注册
final html.HtmlElement element = html.DivElement();
ui.platformViewRegistry.registerViewFactory(getCodeMirrorViewType(),
    (int viewId) {
  return element;
});

/// 初始化codemirror
editor = (editorFactory..paramsProvider = this)
    .createFromElement(element, options: codeMirrorOptions)
  ..theme = 'darkpad'
  ..mode = 'dart'
  ..showLineNumbers = true;

通过简单的初始化配置设定主题和语言模式后后,将HtmlElementView 嵌入Widget 层级中,就可以正常显示代码编辑器。

Fair-Online中代码编辑器的前后端运行原理

当然如果要使代码编辑器具备完善的功能,还少不了对代码进行语法检测分析,通过快捷键触发代码的补全提示等功能,这些也是我们日常开发使用的AndroidStudio 和VSCode 中具备的必要功能。

CodeMirror 只是代码编辑器的UI库,对于代码语法的分析逻辑需要自定义,然后组装分析结果交由CodeMirror 的Hint和Doc操作对象进行实际的展示。在Fair-Online 的架构中,Flutter 和Fair 的语法分析由Dart 编写的服务端完成,具体的运行原理如下图所示:

  • 在Flutter Web 监听输入和组合快捷键,触发分析请求
  • Dart Server 通过Analysis Server 和Fair 语法分析插件生成分析结果,并返回给Web 端
  • Web 端通过将结果转化为具体的操作对象,交由代码编辑器来进行文本操作或提示弹窗显示
  • 通过Dart 和JS 的互操作性调用CodeMirror 的具体操作API

Flutter 语法分析

Analysis Server

Analysis Server 是官方提供的Dart 语法分析服务,开发者熟悉的AndroidStudio、VSCode 等IDE 都是通过跟它的交互,完成语法静态分析、代码提示、代码补全等功能。

以Android Studio 为例,语法检测核心是Analysis Server,Dart 插件负责监听用户代码修改,每当代码有改动时,插件会通过Socket 同步给Analysis Server,Analysis Server 分析结束后将结果同步给Dart 插件,Dart插件根据Analysis Server 返回的事件类型进行处理,最终通知Android Studio 刷新界面。详细时序图如下:

以上是IDE 中实现Flutter 语法检测的过程。

自定义语法检测

在Fair-Online 的代码编辑器中,除了Flutter 语法分析,还需要支持自定义规则的语法分析检测,例如在布局与逻辑混编场景下,需要将代码块中的逻辑语句转化为Fair 支持的语法糖。

对于自定义规则语法分析,我们可以通过自定义语法插件去实现。

语法插件的挂载问题。通过配置目标工程的analysis_options.yaml 实现。Analysis Server 启动时会寻找这个配置文件,然后加载对应的插件。

自定义语法检测插件核心实现如下:

  • 输入的是经过处理后的编译单元,里面包含由Dart 源代码转化而来的完整的抽象语法树结构。
  • FairVisitor 首先会遍历抽象语法树,检查是否包含FairPatch 注解。因为只有包含FairPatch 注解的Flutter 代码,才会被Fair 识别、编译。
  • 接下来包含有FairPatch 注解的class 信息,交由FairClassVisitor 处理。
  • FairClassVistor 会遍历class 中所有方法,根据方法类型分别交由特定的Visitor处理。每个Visitor 对应的是一个 Fair 语法糖。Visitor 之间是互相解耦的,后续可灵活扩展。
  • 最后每个Visitor 遍历方法体,进行语法检测,分别返回语法分析的结果。

自定义语法检测实现效果如下:

Flutter 在线编译预览

在我们使用Flutter 开发移动端应用时,借助Debug 模式下的Hot Reload 功能可以实现在手机或模拟器上面快速的预览代码改动。在传统的低代码平台上因为采用拖拽控件的方式天然的支持对UI 效果的把控,而Fair 云开发平台上面采用在线编写代码的方式,需要在网页中快速预览所写代码运行后的效果。

Flutter Web上如何在线预览代码运行效果

在代码编辑器的部分中我们提到了Flutter 在Web 平台上运行的核心是dart2js,区别于移动端,在Web 上 dart2js 通过将dart 编译的中间产物dill 转化为JS 来实现。

由于构建Html 标签或者使用Canvas 来展现UI 的逻辑都在js中,按照这个思路我们可以将在线编写的代码通过 dart2js 编译,然后嵌入Html 标签中进行预览。但如果处于同一window 和dom 下的话,资源和JS 环境会共享,会引起冲突,这时需要iframe 标签来解决这个问题。iframe 标签承载了一个单独的嵌入的窗口,它有自己的 document 和window,所以大致思路就是将在线编辑的代码转化为JS 后注入一个iframe 内进行预览。

Dartdevc编译器

Dart 开发编译器(dartdevc,也称为DDC) 一般用于Flutter Web 开发时使用Chrome 运行和调试。区别于 dart2js,dartdevc 支持增量编译,所以在开发调试中可以做到类似移动端Flutter 中HotReload的效果。dartdevc 通常需要配合webdev 一起使用,webdev 是使用Dart 开发和部署Web 应用程序的命令行工具,比如监听文件变化触发重建和重新部署就尤其负责。

Fair-Online编译预览前后端原理

出于对在线编译速度的考量,Fair云开发平台在Dart 后端上面使用dartdevc 替代dart2js 进行对代码的编译,生成的JS 产物返回前端注入到iframe 中进行效果的预览,具体实现流程如下图所示:

  • 用户在Fair云开发平台在线编写代码
  • 前端通过用户输入发起编译预览请求
  • 后端接收请求,通过dartdevc 编译器对工程代码进行编译,将生成的JS 产物返回给前端
  • 前端将返回的JS 产物注入到iframe中进行效果的预览

支持我们

欢迎大家使用 Fair,也欢迎大家为我们点亮Star。

Github地址:github.com/wuba/fair

Fair官网:fair.58.com

作者:58技术
链接:https://juejin.cn/post/7182537593001934909

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 230,362评论 6 544
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 99,577评论 3 429
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 178,486评论 0 383
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 63,852评论 1 317
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 72,600评论 6 412
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 55,944评论 1 328
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 43,944评论 3 447
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 43,108评论 0 290
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 49,652评论 1 336
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 41,385评论 3 358
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 43,616评论 1 374
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 39,111评论 5 364
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 44,798评论 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 35,205评论 0 28
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 36,537评论 1 295
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 52,334评论 3 400
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 48,570评论 2 379

推荐阅读更多精彩内容