1
前言
Fair-Online 是面向Flutter 开发者,提供从Flutter 在线开发,到实时编译预览,打包发布、动态下发端侧更新,实现Flutter 线上动态化的一体化云开发平台。开发者无需配置Flutter 开发环境,在线开发调试代码,即时编译预览,所见即所得,结合58开源团队打造的Flutter 动态化框架 Fair 及热更新平台 FairPushy ,实现Flutter 线上动态化。
目前Fair 云开发平台已在Github 开源:
Fair-Online Github
在线体验地址:
fair-online.58.com
2
Flutter低代码
熟悉Flutter 的小伙伴应该都了解过 FlutterFlow,它是目前比较完善的Flutter 低代码平台,面向的是Flutter 零基础开发者。开发者无需了解Flutter 的控件体系及语法规则,只需使用平台提供的微件和复合组件,拖拽生成页面即可。对于业务逻辑处理,比如网络请求、事件Action处理等,是通过可视化的属性编辑完成,平台会根据开发者的操作生成对应的Flutter 代码。
在体验使用FlutterFlow 的过程中,我们也发现一些问题。首先,对于页面UI开发,如果要实现一个功能复杂,页面层级较多的UI,使用拖拽组合,会变得非常繁琐困难,这对Flutter 开发者是不够友好的开发方式;其次,对于复杂业务逻辑的处理,比如网络请求,事件Action处理等,使用可视化属性设置,开发也比较繁琐,且学习成本较高。
所以,针对上述问题,在技术选型上,区别于FlutterFlow 等低代码平台的拖拽编辑实现,Fair-Online 是面向Flutter 开发者,提供在线代码编辑器,辅助以可视化的工程、页面、组件创建、编辑,以实现Fair 开发提效,且几乎没有额外的学习成本。为了方便不熟悉Fair 的小伙伴快速上手Fair 开发,平台提供了常用的工程、组件模板以及网络请求等业务逻辑,开发者在创建工程、页面时可选择模板创建,然后二次编辑。
3
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 中核心功能的实现。
4
在线代码编辑器
4.1 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 文件。
4.2 Flutter Web与JS的互操作性
Flutter 在移动端的生态丰富,但是在Web 上面就差了很多,目前的Flutter Web 在开发中很大程度上依赖了Web 上丰富的三方库,所以能够与JS 的函数互相调用是很重要的能力。
不同于Flutter 在移动端上面与webview 的交互方式,由于Flutter Web 是运行在浏览器环境中的,并且本身Dart 也会经dart2js 转化为JS 代码,所以在Flutter Web 上面通过dart:js 或是packages:js 可以很轻松实现Dart 和JS 互相调用。
4.3 技术选型-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;});/// 初始化codemirroreditor = (editorFactory..paramsProvider = this) .createFromElement(element, options: codeMirrorOptions) ..theme = 'darkpad' ..mode = 'dart' ..showLineNumbers = true;
通过简单的初始化配置设定主题和语言模式后后,将HtmlElementView 嵌入Widget 层级中,就可以正常显示代码编辑器。
4.4 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
5
Flutter语法分析
5.1 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 语法检测的过程。
5.2 自定义语法检测
在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 遍历方法体,进行语法检测,分别返回语法分析的结果。
自定义语法检测实现效果如下:
6
Flutter在线编译预览
Flutter 在线编译预览
在我们使用Flutter 开发移动端应用时,借助Debug 模式下的Hot Reload 功能可以实现在手机或模拟器上面快速的预览代码改动。在传统的低代码平台上因为采用拖拽控件的方式天然的支持对UI 效果的把控,而Fair 云开发平台上面采用在线编写代码的方式,需要在网页中快速预览所写代码运行后的效果。
6.1 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 内进行预览。
6.2 Dartdevc编译器
Dart 开发编译器(dartdevc,也称为DDC) 一般用于Flutter Web 开发时使用Chrome 运行和调试。区别于 dart2js,dartdevc 支持增量编译,所以在开发调试中可以做到类似移动端Flutter 中HotReload的效果。dartdevc 通常需要配合webdev 一起使用,webdev 是使用Dart 开发和部署Web 应用程序的命令行工具,比如监听文件变化触发重建和重新部署就尤其负责。
6.3 Fair-Online编译预览前后端原理
出于对在线编译速度的考量,Fair云开发平台在Dart 后端上面使用dartdevc 替代dart2js 进行对代码的编译,生成的JS 产物返回前端注入到iframe 中进行效果的预览,具体实现流程如下图所示:
- 用户在Fair云开发平台在线编写代码
- 前端通过用户输入发起编译预览请求
- 后端接收请求,通过dartdevc 编译器对工程代码进行编译,将生成的JS 产物返回给前端
- 前端将返回的JS 产物注入到iframe中进行效果的预览
作者:万兵
来源:微信公众号:58技术
出处:https://mp.weixin.qq.com/s/OX17P04KQi29EfxHc9jMeA
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。