Flutter 热更新无侵入方案(探讨)

7,118 阅读6分钟

Flutter 热更新无侵入方案(探讨)

第二篇 Flutter 热更新无侵入方案(生成运行时库)

第三篇 Flutter 热更新无侵入方案(生成注册表)

第四篇 Flutter 热更新无侵入方案(插件中心)

目前我将开发放在了社区 github.com/flutter-run… 希望有志向小伙伴一起开发

起因

在去年年初的时候,收到领导授意让研究关于 Flutter 低代码的东西,我找到了刚刚发布商用不久的 FlutterFlow 准备作为借鉴的类型。但是对于 FlutterFlow 其实面向于从 0 到 1 的开发,并且从 0 到 1 都是通过配置做程序,这个应该没有多少家可以接受。

这个方案也不适用于我们的团队,虽然带着我只有七八个人。我希望可以直接在日常的开发中可以帮助他们提高编程效率,让团队人喜欢上这种形式的开发,而不是让他们扔掉平时编码形式,接受不喜欢的配置生成代码的形式。

为了能够做到这些,我提出了 Flutter 低代码 IDE 的概念,通过专门的低代码的 IDE 更加可以帮助团队的组员。

Flutter 低代码 IDE 的规划

对于 Flutter IDE 的规划,当时主要规划做了一下的内容,虽然实现起来十分的困难。

  • 支持配置通过 Mustache 生成 Flutter 的代码
  • 支持通过 Analyzer 的 AST 能力分析现有工程生成配置
  • 通过 Dart LSP 支持代码智能提示
  • 支持动态运行 IDE 插件(Flutter 工程)
  • 支持预览工程 Widget 组件(类似 SwiftUI)
  • 支持打包自动将代码转换为自定义 DSL 支持全量热更新
  • 支持 IDE 插件市场,支持作者发布插件
  • ......等等

我对于这个所有的想法都基于这个 Flutter IDE 实现的(类似 Xcode),并且要求这个 macOS/Windows 的开发工具用纯 Flutter 来实现,不然后续一些功能无法做到。

团队的室友建议我做 VSCode 插件,毕竟 VSCode 做出来利用插件进行编程不比自己写出来好用,香?这个的确,但是奈何自己没有任何的前端的基础,根本不懂 JS,这个也是限制我选取技术方案的一点。

Flutter 热更新方案想法

对于 Flutter 低代码 IDE 关于插件化的想法,并不是完全为了插件而插件。而是不同项目的代码规范不一样,开发者可以用利用自己的插件将代码解析成为能被 Flutter IDE 识别的配置或者自定义其他功能,这就要求这一款 IDE 必须支持动态运行插件。

最开始的时候,我是通过做了一套自动管理/运行 Dart 命令行的系统 DCM,后来发现官方自带这样的命令,但是还是没有自己写的可以随心的添加适合的功能还用。

对于动态运行 Dart 命令行的,通过传递唯一的标识符从本地获取请求的 JSON 文件和响应的 JSON 文件,确实做到了我可以动态安装和运行一些自定义逻辑的能力,但是做不到可以运行拥有界面的插件。

最开始自己做了一些规则,插件可以按照我的规则配置,之后通过 Dart Annation 注解生成 YML,然后让 IDE 再还原,但是这种都需要 IDE 提前内置这种组件,不太灵活。

后面我就看了目前市面上关于动态运行 Flutter 的方案,但是都不是很满意,然后我就研究一些一套无改动的动态运行 Flutter 方案,也是为了后续一些功能。

Flutter 热更新技术的实现

对于 Flutter 热更新的要求无非就是支持

  • 修复逻辑打包发布,将需要热更新的类或者方法打成更新包,等待下一次页面进入或者执行方法动态运行。(无新增第三方)
  • 新增了功能,做了新办法,直接发布运行。(类似游戏版本更新,新增第三方)

对于上面的支持主要通过做一套动态解析器,自定义 DSL 来实现,下面简单说一下大概的步骤。

生成动态运行库

通过 AST 写一套工具分析需要支持动态更新的工程,将现有工程代码的类/方法生成可以通过字符串调用的的动态运行库,比如生成下面的代码。

class $MyWidget$ extends FlutterRuntime(需要我们写的基类) {
		static MyWidget create(Map parameter) {
			return MyWidget(title: parameter["title"] as String);
		}
}

上面的代码只是一个例子,本质就是通过将改动的代码生成 JSON,之后按照 JSON 进行还原逻辑。

假设你的工程只有依赖有50个第三方库,理论上包含你自身的工程,就需要新增 51 个动态运行库,这个包增大和运行速度减慢,这个有待考证,目前主要是方案的可行性

动态解析器

比如新写了一个逻辑,怎么才能动态运行呢?我的想法是写一个动态解析器,

image-20230515101300403

比如 App 是整个最外层的运行器,里面存放 常量值,变量值。里面有很多个 Class 的运行环境,包含了 Class 里面的变量等等。每个 Class 还有多个方法的运行环境,方法里面有方法变量,参数等。在方法内部有各种 for/if/else if/foreach 等小区间的运行环境。

将改动的代码分解成可以被动态解析器运行的自定义 DSL 之后调用动态运行库运行

支持新增第三方库

对于后续新增的功能,或者修复bug(用到新增第三方很少)。需要线上的版本支持,这个怎么做呢?

这个就需要将新增的功能逻辑和修复的功能逻辑进行分析,进行拆分到可以被线上 App 包含的动态运行库只是的颗粒程度。

image-20230515102548036

工具会把 1 中暂不支持动态解析的代码解析成 2 中已经支持的自定义 DSL

关于现状

去年团队虽然也有七八个人,但是都是我一个人去研究,没有任何人讨论,所以方案有一些不程序。今年被领导要求学 Unity 3D,团队人员也在去年优化的剩下带着我三个人,另外的两人要维护公司项目,也无力抽身。我现在更是无力研究任何关于 Flutter,只想着赶紧入门 Unity3d 开发承接公司的项目。

如果有大佬觉得这个方案可以做,可以联系我可以一起讨论,我有空也一起写,但是上班时间确实没有多出来的精力弄了。如果有大佬觉得方案有问题可以提出来,或者有其他更好的方案也行。