「如何实现流动式软件发布」线上课堂开课啦,快来报名参与课堂抽奖吧~ 了解详情
写点什么

纯 Dart 的挑战:美团外卖 Flutter 动态化实践

2020 年 12 月 08 日

纯 Dart 的挑战:美团外卖 Flutter 动态化实践

“一套代码,多端运行。”是很多开发团队的梦想,直到 2018 年 12 月 5 日,谷歌正式发布 Flutter 1.0 版本,前端开发者向这一梦想前进了一大步。Flutter 仅用了不到一年的时间就在 GitHub 和 StackOverflow 上获得了比 React Native 更高的知名度。Flutter 提供了一整套从底层渲染逻辑到上层开发语言的完整方案,有跨平台、高保真、高性能等优点。也正因为这些革命性的优点,从发布到现在,它的热度一路攀升,受到了很多开发者的热切青睐。目前各大公司的 Flutter 落地实现各有不同,此次 InfoQ 记者采访到了美团外卖的技术专家,Flap 动态化项目的负责人董尚先,为我们分享了美团外卖采用 Flutter 的实践与经验。(相关视频分享已在线上录制完毕,预计在 1 月左右放出)


选择技术栈要看业务特点


美团外卖的用户端(下文用 C 端表示)和商家端(下文用 B 端表示)分别采用了不同的技术方案,原因是两端的业务特点不尽相同。二者均有美团标准化的 web 容器,但 C 端的用户量更大,对动态性要求更高,在低 pv 页面用 React Native 来做页面级的跨端动态化较多,在高 pv 页面使用美团外卖自研的区块级动态化和触达提示,最终支撑外卖 C 端的动态性业务需求。


相比之下,B 端的页面复杂度更高,C 端商品上的一些小标签,小按钮,在 B 端配置时有很深的层级和复杂的联动组件。此外,B 端需要关联到发配送,打印机等复杂逻辑,在实际开发时更加耗时。所以,B 端在技术选型时更看重跨平台框架的性能瓶颈与双端一致性。初期,美团外卖商家端也曾尝试过用 React Native 作为跨平台的技术方案,但过渡版本无法达到预期的要求,所以后期站队 Flutter 技术栈。


确定技术栈后的思考


Flutter 的“多端一致”和“渲染性能”上的优势让其他跨端方案很难比拟。虽然 Flutter 的成长曲线和未来前景看起来都很好,但不可否认的是,目前 Flutter 仍处在发展阶段,很多大型互联网企业都无法毫无顾虑地让全线 App 接入,而其中最主要的顾虑是包大小与动态化。


首先是包的体积问题,有很多大厂都做过 Flutter 的产物瘦身与包体积瘦身,美团也对此进行了尝试,最终优化后 Android 的包体积降低了 95% 左右,iOS 降低了 30% 左右。


其次是动态化,其实动态化与包体积之间是存在联系的:动态化可以带来动态性,从而可以动态下发 bundle,就可以间接地减少包的体积。目前尚未看到成熟且大范围落地的动态化方案。与此同时,美团外卖商家版的业务发展对动态化的诉求越发强烈,因此美团内部立项了 Flap 项目,目标就是支撑 Flutter 动态化能力。


为什么要用纯 Dart 的动态化方案


可能基于其他语言做动态化的惯性思考来看,相对方便点的实现是用 Dart 做视图 UI 部分,采用 JavaScript 处理逻辑,事件回调的时候用 callbackid 来标识, 这样的做法会带来很多限制:


  • 开发时要分开写;

  • 将存量的 Flutter 普通页面 迁移到 动态化 成本太大;

  • 运行时跨端通信损耗;

  • 并且视图和逻辑需要完全隔离的,视图中的逻辑部分很难处理。


美团 Flap 项目的基本目标是做一套完整的业务解决方案,支持大厂应用的复杂业务,而不是一些重展示轻交互或是 UI 与动态模板这样的方案。因此仅使用纯 Dart 语言去做,在不引入其他技术栈的情况下,攻克视图与逻辑一体化的动态化方案。这么做的好处基本就是上面列出的那些限制的反面:


  • 可以保持开发习惯与普通 Flutter 一致;

  • 写完后的代码可以在 Flutter 动态化和 Flutter 普通(AOT)上同时运行;

  • 并且在运行时没有跨端通信的损耗;

  • 最大的优点是可以迁移存量页面。Flutter 已经发展了一段时间,各个大厂都有大量的 Flutter 存量页面,使用常规方案迁移至动态化就需要重写代码,使用此方式可以接近 0 成本将其迁移至动态化,不用更换语言重新开发。


纯 Dart 所带来的挑战


Dart 是一种强类型、跨平台的客户端开发语言。具有专门为客户端优化、高生产力、快速高效、可移植(兼容 ARM/x86)和原生支持响应式编程(Stream & Future)等优秀特性。Dart 语言既有静态语言的特性,也支持部分动态语言的特性。


使用纯 Dart 的方式开发动态化的难点在视图逻辑一体化。相当于在 Dart 侧开发一个针对 Flutter 语言特性的解释器,需要对 Dart 整个语法特性有非常全面的认识。这里面的工作量也是很多的,我们在前期需要做很多的评估与拆解:


  • 需要在整体架构上区分 “准备符号”与“运行”两个阶段;

  • 需要考虑到视图和逻辑两个场景;

  • 需要考虑到系统类与自定义类的两种调用与加载方式;

  • 需要用一套合理的 bundle 管理机制做好相应的隔离与约束。


除此之外,还需要同步搭建支撑动态化的技术生态与工具,包括 IDE 语法检测插件(把问题前置到开发阶段)、代码生成工具、降级容灾系统等。对开发同学的技术储备要求较高。


业务落地只是目标之一,更重要的是在项目的实践过程中发现框架存在的问题,完善各类语法特性支持,提高在复杂的场景下的兼容性,促进框架的完善。在不断打磨中总结出合理的调试方案、操作步骤与协作方式,不断提升开发效率与体验。完善动态化基建及工具链建设,完成动态化流程的自动化与工程化,进一步降低转换与开发成本。


实际进展与开源计划


线上有些资料因为发布时间的问题,所以消息可能有滞后,现在已经 12 月上旬了,也快年底总结了,就以现在的口径为准吧。 目前外卖业务已经真实上线了 100+ Flap 页面,40+业务模块。目前外卖商家端的跨端与动态化覆盖度达到 90% 左右。 且已经在多个业务线实行需求动态发布流程,可动态上线的需求占比 60~80%,整体也是达到了年初时的预期。


至于开源应该到 21 年 Q2Q3。其实 sdk 很早就开发完了,之后是在通过业务落地来反哺 sdk 框架的打磨。 Flap 团队之所以没有第一时间开源,是因为觉得自己业务没广泛运用就开源是在“耍流氓”,后来我们也的确是优化了挺多问题。 下半年在能力和生态都建设的不错,一些边界的语法逻辑也都有了比较优雅的解决方案,接下来会在 Flutter 页面“零成本”转动态化的实施上再完善下,应该在 21 年 Q2Q3 左右开源。


Flutter 的使用体验与性能


在开发时,Flutter 这种累砖块的布局方式写起来“很爽”,客户端同学很好上手,大家反应写起代码来很快,在开发效率上已经有了不错的表现。


Flutter 的双端一直性做的很好,经常很多 Android 同学开发时拿 iOS 模拟器调试(因为 Android 调试一般都需要使用真机比较麻烦),iOS 模拟器开发完需求之后,拿 Android 设备再一跑大多都没问题。Native 基本就是提供好一些端能力的桥就 ok 了。性能方面,Flutter 和 Native 也很接近,没有 bug 的情况下,帧率也都是 59 朝上,渲染成功率也都是三个 9 以上。


在质量方面,目前外卖商家端的客户端 crash 和 Dart 异常是分开采集的。Flutter 大量覆盖之后 crash 占比中只有不到 10% 的量是由 Flutter 引起的,Dart 异常率不足千分之一。有时候上报的 Dart 异常并不会影响到用户的体验,例如有时候代码缺陷关了一个弹窗,报了一个异常,但弹窗依旧正常关闭了等等。


总的来说,使用 Flutter 后,在效率、质量、性能三个关键点上都达到了的预期,今年年底前,美团外卖商家端应该会将 Flutter 动态化覆盖至 80%以上。


跨平台开发更应该是百花齐放


从 2010 年 Android 伴随 Android 2.3 大火到 2013 年 iOS 伴随 iOS 7 进入大家的视野以来,客户端每年基本都有大新闻,2014 年 H5 的广泛应用让大量项目补充 Hybird 能力。  然后 2015、16 年 React Native 和 Weex 相继开源,大家先后投入到跨平台的开发。2017 年小程序和 PWA 先后登录,但 PWA 在 2018 年并没有达到人们期待的高度, 小程序则是稳扎稳打,移动端的流量也在逐步像小程序倾斜。但小程序的问题是巨头公司太多框架太多,谁都想做最大的平台,标准暂时统一不起来,还有一些路要走。 然后 2018 年 Flutter 1.0 出台,并且逐步有后来居上的优势,优点前面讲过了,在 GitHub 上的 star 数也是逐步超过了 Weex 和 React Native。


董尚先表示,目前 React Native 还是很强大,因为 React 互通的生态很多。但从长远目光来看,他觉得 Flutter 有成为商业 721 法则中的“7”的潜力。最大的特点 Flutter 是自渲染引擎,Flutter 的 embedder 层是非常轻薄的,同时也是目前跨端数量最多的,可以跨 6 端:


iOS / Android / Web / Linux / Mac / Windos 并且新系统 Fuchsia 也很大可能使用 Flutter 引擎 + Dart 语言。


目前许多大厂在同时使用多套跨平台方案,而不是单从某些标准抛弃其他择其一。未来一段时间内基本会过渡并维持到「内嵌 web 容器 + 少量 Native(端能力相关)+  Flutter / React Native 二选一+ 小程序」这样一个组合。


致客户端同学:学习跨平台技术栈


对于客户端同学,学习跨平台技术栈基本是现在 ROI 最高的事, 你需要结合自身业务的特点和自己公司的大环境,深度学习一门跨平台技术栈,可以是 Weex,可以是 Flutter,也可以是 React Native,然后先学明白一种,然后慢慢做到“一超多强”,其他的跨端也可以做到相对了解,写个 Demo 之类的。


关于学习方式,我建议最好系统的学习,你可以找一个风格适合自己的的 Flutter 专栏或博主把他的公众号的文章顺序读一遍。当然了,极客时间也是个很好的学习平台,里面也是有很多大牛会把一门课系统的教学一遍十几个课时,Flutter 在这里也有系统的学习课程,学习之后会有比较系统的技术储备以及对应的自信。


作者介绍


董尚先,美团技术专家。2015 年加入美团,经历了美团外卖的多个发展阶段,先后任职于用户端和商家端。曾主导外卖用户端架构升级、无人值守的自动化流程体系等项目。致力于提升研发效率,同时也是移动端领域新技术的爱好者,负责多项新技术在业务落地中的难点攻关,目前拥有 10 余项国家发明专利。现作为 Flutter 动态化项目的负责人,探索客户端 App 的最终形态。

2020 年 12 月 08 日 08:003325

评论 2 条评论

发布
用户头像
Flutter哪来的动态化?不就仅仅支持跨端吗?
2021 年 06 月 23 日 12:25
回复
用户头像
传说中的标题党?
2020 年 12 月 22 日 17:38
回复
没有更多了
发现更多内容

谈谈 WebRTC 的 SDP Unified Plan

拍乐云Pano

WebRTC

视频录制后有噪音怎么办?教你简答几步去除视频噪音!

奈奈的杂社

阿里巴巴的“双11”高并发秒杀终极版教程!(Java语言设计)

云流

Java 编程 程序员 架构

走完线上 BUG 定位最后一公里

阿里巴巴中间件

可观测性 bug bug修复

阿里开发7年大牛:只需一篇文章吃透Android多线程技术,好文推荐

欢喜学安卓

android 程序员 面试 移动开发

LeetCode题解:641. 设计循环双端队列,使用数组,JavaScript,详细注释

Lee Chen

算法 LeetCode 前端进阶训练营

开发知识 | 即时通讯是怎么做到的?

APICloud

前端开发 即时通讯 APP开发 小程序制作 开发技巧

破解class文件的第一步:深入理解JAVA Class文件

华为云开发者社区

Java JVM 索引 class文件

合约跟单系统搭建,合约一键跟单app

13823153121

流程引擎介绍

上海派拉基础研发

流程

使用CrossOver安装第三方软件

懒得勤快

架构实战营模块二作业

刁寿钧

架构实战营

腾讯二面:MySQL的半同步是什么?

程序员小毕

Java MySQL 程序员 腾讯 面试

redis常见应用场景

Sakura

四月日更

悲观锁与乐观锁的实现(详情图解)

Java架构师迁哥

万字精华:好好巩固你的Nginx知识体系

学Java关注我

Java 编程 架构 程序人生 计算机

NumPy之:数据类型

程序那些事

Python 数据分析 Numpy 程序那些事

一个码砖的码农,在InfoQ写一年博客,出书了?

小傅哥

Java 设计模式 小傅哥 架构设计 码农出书

泉州有了一个水务大脑,用AI守护“绿水青山”

百度大脑

AI

编曲新手可以用什么编曲软件?

奈奈的杂社

线程的故事:我的3位母亲成就了优秀的我!

王磊

Java 线程 多线程

饿了么EMonitor演进史

阿里巴巴中间件

可观测性 饿了么 emonitor etrace

rrxjava原理,手持4个大厂offer的我,吊打面试官系列!

欢喜学安卓

android 程序员 面试 移动开发

加密原理详解:对称式加密VS非对称式加密

Java架构师迁哥

Python OOP-1

若尘

面向对象 oop 面向对象编程 Python编程

自从有了他,再也没有担心过环境部署~

MY

部署与维护

聪明人的训练(二十三)

Changing Lin

4月日更

一周信创舆情观察(4.12~4.18)

统小信uos

GitHub开源:4行代码实现《黑客帝国》数字雨特效

不脱发的程序猿

GitHub 程序人生 开源项目 四月日更 黑客帝国

Android组件化和插件化开发

寻找生命中的美好

android 组件化 插件化

Rust从0到1-代码组织-模块

rust modules 模块

纯 Dart 的挑战:美团外卖 Flutter 动态化实践-InfoQ