前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Flutter Web - 让 Web 与 APP UI 一致的另一种可能

Flutter Web - 让 Web 与 APP UI 一致的另一种可能

作者头像
Swift社区
发布2022-12-12 17:31:17
1.3K0
发布2022-12-12 17:31:17
举报
文章被收录于专栏:Swift社区Swift社区

前言

当产品说要把所有移动端(小程序、H5、APP)等 UI 做成一致,又不想投入更多的开发人力。那作为开发,有哪些方案可以用呢?

  1. 整体 Web 化,比如 Canva 就是完全套壳的 APP,用了一套 Web 响应式布局,适配了 All。但缺点也很明显,在 APP 上只能是通过 webview,会频繁的白屏及重绘(看滚动条位置就能看出来,保存不住上几个页面的页面状态),更搞笑的是没做离线化,弱网络打开 APP 会卡在 launch 页,首页都进不去 [手动狗头]。
  2. uni-app 等跨端方案, 好几年前笔者也了解尝试过,这类技术优缺点也很明显,如果是开发简单 App,确实可以一把梭。但凡需要体验更优雅点、功能更复杂点就需要花费几倍力气。
  3. 就是本文要说的 Flutter 了,可以参考 美团外卖在 Flutter Web 上的实践。

在 Flutter 3.0 时代后,Flutter 官方算是进一步优化了 build web 的一些问题,减少了包体积,至此,笔者也由于某些原因兴(bei)趣(po)满(wu)满(nai)的开始尝试这大前端极致互卷之路。

思考方案

用 Flutter 来做 Web 最主要的是想复用 APP 的 UI。(其他方面确实赶不上直接用 React / Vue 来开发来的舒适。特别是需要更为重视 SEO 的业务,Flutter 官方对 SEO 都没有任何建议)

先看一下总体架构设计:

这个设计的目的:

  1. 最大程度共用 App 的 Flutter UI 组件。
  2. 尽可能的复用 Web 现有的能力。
  3. 要支撑 Flutter Web 和 Vue Web 页的混用。
  4. 后期可以方便替换成 Rust 完成前后端业务能力大一统。

那其实重点的需要有一个通信层,让 TS / JS 与 Flutter web 可以优雅的通信。

通信层

让 Flutter 开发同学只关心 UI 展示,让前端同学只关心业务实现,尽可能减少沟通及语言学习成本。

那其实通信层上就需要做到双端无感,这很容易想到使用 codegen 的方式(codegen 会单独开一个专栏来聊一聊)。

代码核心上,主要是使用 Flutter 提供的官方一方库 https://pub.dev/packages/js[1] , 虽然它的版本是 0.6+,没有到 1.0 正式版,但隶属于 dart-lang/sdk 还是可信赖的。

在研究了该库的 example https://github.com/google/chartjs.dart/ (google 组织下,也是很有保证的)后发现了一个官方使用的 codegen 生成 chartjs.dart 类的工具。

https://github.com/dart-lang/js_facade_gen[2] 》根据 TS 代码生成 dart 抽象调用层。

在各种挠头尝试下,最终确认这库是用不了的 [手动狗头]

用不了的原因也很简单

如上图所示,虽然这库也是在 dart-lang 中,但这库已经3年没更新了,Flutter 这3年大大小小也发了几十个版本,生成的 dart 代码上林林总总各种报错不能用 ...

那是否要重新造轮子?

在研究了它的源码后,发现其实也还是对 TS 的 AST 进行字符串处理(codegen 的本质就是字符串处理)

那我们就可以改造源码的方式进行本地使用。

例如去支持生成 Flutter 空安全语法:

也做了不少增强性工作,原因是这两点:

  1. 经过验证,虽然 Flutter 调用 JS 没问题,但 JS 对象返回后在 Flutter 上无法被解析,而且在 dart2js / dart2jsdev 上,两者的 JS 对象还是不同的,根本没法直接使用。
  2. 就算把 JS 对象转换成 Map,也不符合我们对 API 的要求,我们希望的是 JS 对象完美体现在 Flutter 上,这样模型层就无需写两遍。

所以我们在 TS 中增加了 @DartObject 注解来做定义,通过内置 json_annotation 直接生成 Flutter Model(当然这需要执行额外的命令,但我们把它封装成一个 vscode extensions 即可很方便使用)。

代码上只要写 TS 代码即可。

代码语言:javascript
复制
/**
 * 首页模版 Model
 */
@DartObject()
export class GDHomeTemplateListModel {
  /**
   * id
   */
  id?: string
  /**
   * 模版名称
   */
  name?: string
  /**
   * 预览图
   */
  preview?: GDHomeTemplateListPreviewModel

  test?: string
}

不能添加视频,所以不太好描述 - -|

举个例子,测试是模版接口调用

下图是 TS 通过 fetchAPI 实现接口调用的测试代码

下图是 Flutter 通过生成的 GDModuleAPI.home.fetchTemplates 方法直接调用 TS 层代码

可以看到 Flutter 正常使用 TS 定义的模型了

再放一张测试结果图:

可以看到,接口请求真实发生且已将模版列表渲染成功。

结论

可以看到过程上做到了极大解耦:

  1. Flutter UI Components 开发
  2. JS API 开发
  3. Flutter 页面拼装 JS API 与 Flutter UI Components

后续

本文主要是记录下调研过程,整体方案已经是可用的,接下来就会进入到方案开发。

参考资料

[1]packages: https://pub.dev/packages/js/example

[2]js_facade_gen: https://github.com/dart-lang/js_facade_gen

- EOF -

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-11-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Swift社区 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 思考方案
    • 通信层
      • 结论
      • 后续
        • 参考资料
        相关产品与服务
        云开发 CloudBase
        云开发(Tencent CloudBase,TCB)是腾讯云提供的云原生一体化开发环境和工具平台,为200万+企业和开发者提供高可用、自动弹性扩缩的后端云服务,可用于云端一体化开发多种端应用(小程序、公众号、Web 应用等),避免了应用开发过程中繁琐的服务器搭建及运维,开发者可以专注于业务逻辑的实现,开发门槛更低,效率更高。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档