likes
comments
collection
share

「全网首发」Flutter element embedding 初探(面向 Web 未来)

作者站长头像
站长
· 阅读数 14

本文可能是全网首篇探索 2023 Flutter Forward 中关于Flutter element embedding的文章。

前沿

(是的,没写错,不是“前言”,只因看到这篇文章的你已经走近技术的最前沿了 ~)

Flutter element embedding 是什么?

简单的说,就是把 Flutter 代码当做一个<div>嵌入到 Web 页面中,且可以相互操作。

在这之前,Flutter for Web 想嵌入到 Web 页面中,就只能通过<iframe>的方式嵌入,这个笔者在以前也是尝试过多种奇淫巧技,想让 Vue 代码与 Flutter for Web 页面深度融合,但都不切实际。笔者最后就完全去使用 Flutter 布局实现(Flutter Web - 优雅的兼容 Flutter App 代码)。

为什么说它可能是 Web 的未来?

  1. 现在流行的各类前端 UI 组件库(Ant、Vant 等等),都是被现代前端框架(Vue、React)限制住的,而字节的 semi 虽然是超脱于框架本身,但其实还是被前端语言束缚的。虽然说前端基本可以一统天下,但想进一步在桌面/移动终端提高渲染能力时,能选择的方案就很有限。

这里额外解释下:

比如 RN、weex 等混合渲染方案,但这些方案本身是很难支持纯前端的,演进上就会变成 RN for Web,但这其实不符合前端趋势的。

那如同 uni-app 这种封装全家桶方案,问题是很多,但它在发展上完全可以用 Flutter element embedding 来面向未来(可能换车道也很难)。

  1. Flutter 在 Web 上也是 Skia 渲染的,在复杂场景或者动画下,比 Dom 布局性能上更好,更强大(特别是针对动辄上千个 Dom 标签的页面)。

那它在未来上,完全是可以代替各类 UI 组件库,形成全端共用的组件库。any where any use 。

摸索

只能有“摸索”这个词汇,因为是未来的能力,网上的资料只有大会上的宣讲视频,没有官方文档,没有源码解释,甚至官方 Demo 的地址都没有放出来。好在熟悉 Flutter 的套路,最终在 Samples 中里面找到了示例源码(源码传送门)。

分析产物

官方示例地址:flutter-forward-demos.web.app (网络加载慢显示不出来的话,需要翻🧱)

「全网首发」Flutter element embedding 初探(面向 Web 未来)

如上图所示,官方 Demo 整体是一个 Web 页面,动画效果和双边相互操作上都极为惊艳,The Future is Coming!

我们打开 Chrome 调试工具,可以看到:

「全网首发」Flutter element embedding 初探(面向 Web 未来)

Flutter 就是加载在flutter_target这个<div>上,已经完美的能与 Web 结合在一起了!

再来看看产物大小,这个也是决定这个方案的适用面:

「全网首发」Flutter element embedding 初探(面向 Web 未来)

可以看出最大的文件是canvaskit.wasm2.6M,这个是 webassembly 类型的 Skia 渲染文件,虽然大,但可以看出它是通用的,所以说只需要下载一次即可。甚至笔者觉得未来可能会融入到浏览器标准里。

「全网首发」Flutter element embedding 初探(面向 Web 未来)

Flutter 的执行文件还是我们的老朋友main.dart.js占用 475KB,不能说小,但确实是在可接受范围内的,毕竟 Flutter for Web 还是有分包手段的。

使用 canvaskit 的方式也会带来字体加载的成本,这个后续再研究,毕竟现在商用的 Flutter for web 都是flutter build web来打包 Web 模式,使用系统字体即可,所以极少有人关心字体加载问题(canvaskit 模式需要给引擎指定字体文件)。

尝试运行

(这个步骤花功夫最多的还是在找源码地址上 - -|||)

源码传送门 可以看到,它连个 README 都没写 ...

下载源码后,是运行不了的,因为大家的 Flutter 版本不够超前,需要切换到试验性版本。

这里就额外安利一个工具:fvm flutter 版本管理器 ,不然来回切换 Flutter 版本就变成一个痛苦的开始。

这工具十分好用,在正确安装后,首先我们执行:

fvm releases 

它会列出所有的 Flutter 版本

「全网首发」Flutter element embedding 初探(面向 Web 未来)

我们需要安装的就是 beta 版本的 3.8.0 以上的版本

fvm install 3.8.0-10.1.pre 

执行安装命令,等待安装完成。

执行

fvm list

可以查看我们装过的版本

「全网首发」Flutter element embedding 初探(面向 Web 未来)

这之后,在项目里执行

fvm use

选择当前项目需要的版本(这不会影响其他项目使用)。

「全网首发」Flutter element embedding 初探(面向 Web 未来)

然后就可以愉快的 pub get 了,但要注意一点,都需要在命令前增加 fvm

fvm flutter pub get

fvm flutter run -d chrome

这样,我们就把官方示例源码跑起来了。

「全网首发」Flutter element embedding 初探(面向 Web 未来)

源码解析

加载入口

首先我们要关心是如何把 Flutter 加载到 Web <div> 上去的。

是在 web/index.html 中

「全网首发」Flutter element embedding 初探(面向 Web 未来)

与之前的实现不同,是通过 document.querySelector("#flutter_target") 获取到 Dom 对象,再在引擎初始化中指定 hostElement 即可完成加载绑定。

笔者疑惑:

如果一个页面只能加载一个 Flutter <Div>,那这个方案实用性就不大了。

可能是 Demo 本身只是为了演示 embedding 的能力,所以没有实现,或者还在开发过程中? 按笔者想法,这能力应该要复合 Flutter 多引擎,提供多个 runApp() 入口来绑定是最为合理的。

代码解析

Demo 工程代码很简单,也很惊艳,如大会所说的,JS 这库算是颠覆性设计了。

lib/main.dart

「全网首发」Flutter element embedding 初探(面向 Web 未来)

只要增加 @js.JSExport() 注解,能直接把 Flutter 属性/方法开发给 JS 调用

web/js/demo-js-interop.js

「全网首发」Flutter element embedding 初探(面向 Web 未来)

这个 appState 是什么?我们可以通过控制台打印看一下:

「全网首发」Flutter element embedding 初探(面向 Web 未来)

看出所有的方法都已经注册在 window._appState 上,这个又是怎么实现的呢?

lib/main.dart

「全网首发」Flutter element embedding 初探(面向 Web 未来)

关键就是在初始化的时候,用 js_util 做了绑定。

addHandler() 也同理,只不过注册的是一个回调方法来实现的。

至此,JS 与 Flutter 相互操作就已经理解明白了。


还有一点比较惊艳的,就是可以控制 CSS 属性来改变 flutter 代码样式,如示例中的那样,可以翻转,倒影等等。

当然是 Flutter 整体改变的方式,如果要改变 Flutter 中某一个组件的样式,可能还是要通过 JS 交互来做。

这个代码也十分简单,比如倒影:

先增加样式文件

css/style.css

「全网首发」Flutter element embedding 初探(面向 Web 未来)

按钮触发 class 切换即可 ~

web/js/demo-css-fx.js

「全网首发」Flutter element embedding 初探(面向 Web 未来)

后续

本文只是对 Flutter element embedding 能力初探,按 Flutter 的套路,这能力应该在今年 4月 Flutter 4+ 的版本上就会体现出来,所以大家可以兴奋的搓搓手了。

对于笔者来说,它出现的意义更为重大,不仅当下工作上有一个 Web UI 组件库选型的问题,而且可以无代价的 Flutter 多引擎组件库支持成 Web UI 组件库(快捷传送门:从零开始|构建 Flutter 多引擎渲染组件)。

这条路的坑坑洼洼少不了,目前要解决的问题也很多,需要怀着坚定的决心往前踩才行 ~


题外话,本来想每篇文章都继续坚守 iOS 阵地的,但本篇确实只有 Web + Flutter,所以发到前端 ~~


感谢阅读,如果对你有用请点个赞 ❤️

「全网首发」Flutter element embedding 初探(面向 Web 未来)