使用 Flutter 开发小程序的尝试
Flutter 是一个非常优秀的开发框架,借助 Flutter,开发者可以在 iOS 以及 Android 平台自由地发挥创意,构建交互丰富的、精美的应用程序。
同时,Flutter 官方也支持输出到 Web 平台。不过,就我们在实际在开发过程中的体验而言,Flutter For Web 在移动端的性能表现并不理想,尤其在 Android 中低端手机上,性能问题更为突出。并且,Flutter For Web 产物轻轻松松就超过了 2M,这不符合 Web 的体验。
为此,MPFlutter 团队在一年前就尝试是否可以采取另一种思路,在解决 Flutter For Web 的性能问题的同时,解决产物大小过大的问题。
Flutter For Web 的原理
解决问题的关键,是要深刻理解问题的根本原因,我们通过下图了解一下 Flutter For Web 的基本架构。
Flutter For Web 在 Framework 层与 Flutter Native 几乎没有差异,Framework 层会接管所有动画、手势、滚动事件。而 Framework 以及 Application Logic 代码是通过 dart2js 编译成 JavaScript 的,也就是说,开发者可以使用 Dart 开发应用,然后借助 dart2js 编译成 JavaScript 运行在浏览器上。而最终负责渲染的是 Dom 或是 WebGL。
Flutter For Web 存在性能问题关键在于,JSRuntime 承载了太多职责,既要负责应用逻辑的调度,又要负责布局、手势、动画的计算,用户的每一次交互都需要 Framework 层重新计算,并更新到 Dom 或 WebGL 中。而 Dom 更新又是非常消耗性能的操作。
官方目前正在全力推进 WebGL 渲染目标开发,使用 WebGL 可以避免上述问题,但 WebGL 的兼容性不佳,并且对于文本渲染、特定 Element 元素的支持不甚理想,在中低端安卓机上,也是非常卡顿。
我们的思路
既然问题的根本原因在于 Dom 更新过程开销过大以及 JavaScript 负载过高,那是否可以换一种思路解决问题?
我们是否可以通过一次性导出当前状态的组件树,并尽可能减少 Framework 需要处理的事件,做到性能与功能的平衡呢?
答案是可以的,而且 MPFlutter 正是这么做的,经过调整后的架构如下图。
MPFlutter 会在 Flutter 每帧 Draw 以后,将 Element 树序列化成 JSON,并在对端(Web)反序列化成 Dom 对象,并添加到 document.body 上。
在 Dom 对象上发生的各种事件,如 click / touch 也会以相同的方式回传到 Framework 层,由 Framework 层响应事件并更新视图。
更进一步地,我们可以借助 Flutter Element 的 Diff 特性,差量地通过 RPC 发送 Dom 更新数据,进一步优化性能。
对包大小的优化
对于 Web 应用来说,复杂的组件,必然导致包大小的增加。为此,MPFlutter 移除了 Material 和 Cupertino 组件库,补充了 MPKit 库用于常规 UI 展示。MPFlutter 也将 Painting Rendering 暂时没有用到的代码移除。通过该项措施,初始包大小(main.dart.js)得以精简至 300K 以下。
结论
我们通过减少 Dom 的更新次数,减少 Flutter Framework 的事件处理压力,提升了 Flutter Web 应用的性能,当前成果已经通过 GitHub 开源,并应用在某应用的生产环境中。\
延伸阅读
如标题所言,我们应讲述的是使用 Flutter 开发小程序,但全文只描述了对 Flutter For Web 的改进?那小程序呢?
在下一篇文章,我们将重点关注 MPFlutter 是如何输出到小程序的。
剧透:使用 kbone,我们得以实现同样的 API 调用,输出一致的页面到微信小程序中。
作者:PonyCui
链接:https://juejin.cn/post/7038233068406046757
伪原创工具 SEO网站优化 https://www.237it.com/