Flutter for Web 详细预研

<

div contentScore=”2743″>

作者 白及, 阿里无线开发工程师

背景

Google在最新的Google I/O上推出了Flutter for Web,旨在进一步解决一次代码,多端运行的问题。Flutter for Web还处于早期试验版,官方不建议在生产环境上使用。那么到底它的实际情况怎么样呢?我们做了一次预研。期望这次预研的结果可以帮你决定是用,还是不用FFW。

Flutter for Web原理

Flutter for Web和Flutter在上层都是Dart环境,两者不同的是,Flutter的Dart代码运行在Dart虚拟机中,界面由Flutter引擎处理,通过Skia绘图引擎经由GPU绘制到屏幕上。而Flutter for Web的Dart代码编译成JavaScript,界面上部分转换成标准的html标签,部分转换成通过Canvas绘制的自定义标签,最终构成一个dom树。

这个原理上的差异非常重要,这直接可以让我们通过原理得出下面的结论:

Flutter for Web的一致性和体验上存在矛盾

如果Flutter for Web追求(和Flutter)完美的一致性,势必需要大量使用Canvas去绘制,而Canvas去绘制组件的性能(尤其在移动端)至少不会比html标签好。如果FFW追求性能极限而使用大量标准的html标签,这就会带来和Weex、RN等一样的一致性问题:对于Flutter所有的控件都是一套代码在绘图引擎上绘制,对Flutter for Web如果要使用大量html标签,那如何保证一致性呢?只能靠大量精细的打磨工作了。所以FFW必须要处理好这个平衡。

为啥使用canvas绘制性能不优于手写html呢,定性的从几个角度分析:

  • FFW在canvas上绘制的组件带有很多MD特色的视觉和动画,比如阴影、Z轴变化等,这部分对性能的消耗要大于普通html标签

  • FFW是通过Dart的DSL转成的dom树结构,转化后的dom树十分复杂,不太可能比手写的dom树更简洁

  • 使用canvas的控件,其手势事件的捕获分发都是靠FFW框架自己实现的,emmmm

  • 虽然不排除Google大力出奇迹的情况,但是不管怎样,相同素质的开发人员,相同的界面,性能上也不可能优于html+css+js

另外一点,如果FFW在原理上涉及大量HTML标签的转化,那就势必会涉及到碎片化的处理中,浏览器的碎片化程度可一点都不比Android系统的碎片化小。像Flutter本身之所以被那么多人看重,就是因为其通过绘图引擎这一层,完美的避开了碎片化,保证一致性。

所以最好的平衡就是,只有有限的一部分标准的html标签可以被FFW复用,其必须有几点性质:

  1. 标签本身的功能简单又直观

  2. 最好不要有直接图形化的展示,或者只负责简单的图形化展示(比如画方形)

    那几个比较典型的标签就是

    这种了

Flutter官方就是这么做的,所以我的结论是:

一致性上大体不会存在问题,性能上,FFW应该不会优于纯手写html标签界面。

官方现状&建议

根据官网和Github repo上的说法,我们整理了一下:

  1. Flutter for Web和Flutter目前暂时是两个仓库,官方正在进行合并,没有给出结论。这一点在工程上非常重要,它说明了几个问题:

    目前官方对FFW的成熟度没有信心,同时FFW的迭代速度也很快。

    目前FFW和Flutter最多保证API一样,实现原理差异可能非常大,同时不保证所有控件都已经在FFW上实现。

  2. 官方不建议应用在生产环境

  3. 目前插件能力十分有限,和系统交互的一些能力缺失,比如拍照等。

  4. 性能无法保证,运行会慢,可能会有掉帧

  5. FFW中针对桌面的UI部分没有完成(跟我无线有什么关系?)

  6. 开发中只能在Chrome中调试(又有什么关系?),release版是可以运行在任意浏览器中(除了IE,另支持的最低版本存疑)。

实践

对于这么新的东西,官网上的内容的确不多,而且简单来看这些问题好像也没什么,所以对于到底能不能用,我们还是需要抱着吃螃蟹的心态具体进去预研一下,为了尽快弄清,我计划找一个我们app已经做好的flutter页面,把它迁移成FFW,对整个迁移过程做个评估,再看下页面效果,基本上就能得出结论了。

具体的迁移细节就不提了,官网也有迁移文档,大体上就是这么几个步骤

  1. 安装Flutter for Web的工具webdev

  2. 改SDK依赖,新增Web文件夹(和之前存在的android、ios文件夹同级),新增一些其他文件(index.html, main.dart等)。

  3. 将所有flutter代码中依赖的flutter包,改成flutter_web包

  4. 去掉所有不兼容的代码,比如多语言、路由、Platform.isAndroid等等

  5. 编译运行

实践的主要目的,有以下几个:

  1. 对整体坑的深度和广度有个认知,方便推算出填坑成本

  2. 对FFW整体的性能和体验有个把握,尤其是我们自己的页面跑在FFW上是什么体验。

  3. 对FFW和JS相互调用有具体的了解,如果可行,那复用集团已有能力(比如mtop)的坑就会小很多