纯 Dart 的挑战:美团外卖 Flutter 动态化实践
wptr33 2024-12-05 17:00 25 浏览
“一套代码,多端运行。”是很多开发团队的梦想,直到 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 的最终形态。
延伸阅读:
关注我并转发此篇文章,私信我“领取资料”,即可免费获得InfoQ价值4999元迷你书,点击文末「了解更多」,即可移步InfoQ官网,获取最新资讯~
- 上一篇:玩玩Flutter Web——实现高德地图插件
- 下一篇:Flutter——布局
相关推荐
- oracle数据导入导出_oracle数据导入导出工具
-
关于oracle的数据导入导出,这个功能的使用场景,一般是换服务环境,把原先的oracle数据导入到另外一台oracle数据库,或者导出备份使用。只不过oracle的导入导出命令不好记忆,稍稍有点复杂...
- 继续学习Python中的while true/break语句
-
上次讲到if语句的用法,大家在微信公众号问了小编很多问题,那么小编在这几种解决一下,1.else和elif是子模块,不能单独使用2.一个if语句中可以包括很多个elif语句,但结尾只能有一个...
- python continue和break的区别_python中break语句和continue语句的区别
-
python中循环语句经常会使用continue和break,那么这2者的区别是?continue是跳出本次循环,进行下一次循环;break是跳出整个循环;例如:...
- 简单学Python——关键字6——break和continue
-
Python退出循环,有break语句和continue语句两种实现方式。break语句和continue语句的区别:break语句作用是终止循环。continue语句作用是跳出本轮循环,继续下一次循...
- 2-1,0基础学Python之 break退出循环、 continue继续循环 多重循
-
用for循环或者while循环时,如果要在循环体内直接退出循环,可以使用break语句。比如计算1至100的整数和,我们用while来实现:sum=0x=1whileTrue...
- Python 中 break 和 continue 傻傻分不清
-
大家好啊,我是大田。...
- python中的流程控制语句:continue、break 和 return使用方法
-
Python中,continue、break和return是控制流程的关键语句,用于在循环或函数中提前退出或跳过某些操作。它们的用途和区别如下:1.continue(跳过当前循环的剩余部分,进...
- L017:continue和break - 教程文案
-
continue和break在Python中,continue和break是用于控制循环(如for和while)执行流程的关键字,它们的作用如下:1.continue:跳过当前迭代,...
- 作为前端开发者,你都经历过怎样的面试?
-
已经裸辞1个月了,最近开始投简历找工作,遇到各种各样的面试,今天分享一下。其实在职的时候也做过面试官,面试官时,感觉自己问的问题很难区分候选人的能力,最好的办法就是看看候选人的github上的代码仓库...
- 面试被问 const 是否不可变?这样回答才显功底
-
作为前端开发者,我在学习ES6特性时,总被const的"善变"搞得一头雾水——为什么用const声明的数组还能push元素?为什么基本类型赋值就会报错?直到翻遍MDN文档、对着内存图反...
- 2023金九银十必看前端面试题!2w字精品!
-
导文2023金九银十必看前端面试题!金九银十黄金期来了想要跳槽的小伙伴快来看啊CSS1.请解释CSS的盒模型是什么,并描述其组成部分。...
- 前端面试总结_前端面试题整理
-
记得当时大二的时候,看到实验室的学长学姐忙于各种春招,有些收获了大厂offer,有些还在苦苦面试,其实那时候的心里还蛮忐忑的,不知道自己大三的时候会是什么样的一个水平,所以从19年的寒假放完,大二下学...
- 由浅入深,66条JavaScript面试知识点(七)
-
作者:JakeZhang转发链接:https://juejin.im/post/5ef8377f6fb9a07e693a6061目录...
- 2024前端面试真题之—VUE篇_前端面试题vue2020及答案
-
添加图片注释,不超过140字(可选)...
- 今年最常见的前端面试题,你会做几道?
-
在面试或招聘前端开发人员时,期望、现实和需求之间总是存在着巨大差距。面试其实是一个交流想法的地方,挑战人们的思考方式,并客观地分析给定的问题。可以通过面试了解人们如何做出决策,了解一个人对技术和解决问...
- 一周热门
- 最近发表
-
- oracle数据导入导出_oracle数据导入导出工具
- 继续学习Python中的while true/break语句
- python continue和break的区别_python中break语句和continue语句的区别
- 简单学Python——关键字6——break和continue
- 2-1,0基础学Python之 break退出循环、 continue继续循环 多重循
- Python 中 break 和 continue 傻傻分不清
- python中的流程控制语句:continue、break 和 return使用方法
- L017:continue和break - 教程文案
- 作为前端开发者,你都经历过怎样的面试?
- 面试被问 const 是否不可变?这样回答才显功底
- 标签列表
-
- git pull (33)
- git fetch (35)
- mysql insert (35)
- mysql distinct (37)
- concat_ws (36)
- java continue (36)
- jenkins官网 (37)
- mysql 子查询 (37)
- python元组 (33)
- mybatis 分页 (35)
- vba split (37)
- redis watch (34)
- python list sort (37)
- nvarchar2 (34)
- mysql not null (36)
- hmset (35)
- python telnet (35)
- python readlines() 方法 (36)
- munmap (35)
- docker network create (35)
- redis 集合 (37)
- python sftp (37)
- setpriority (34)
- c语言 switch (34)
- git commit (34)
