京东技术中台 Flutter 实践之路(二)
移动互联网历经高速发展的黄金 10 年,多样的市场需求催化了前端技术不断升级改造,真正的前端大统一时代正在来临,不管你愿不愿意相信,大前端技术的发展趋势已是定势,前进的脚步无可改变。
众所周知,iOS、Android、Web 分别代表着前端技术需要考虑的必要方向,传统的移动互联网开发需要同时考虑多个平台对应的技术研发资源储备,公司开发同一个业务,需要至少三个独立团队参与评审及开发,测试也需要至少三倍工作量以完成对应平台的代码测试,这样的生产效率已无法满足业务快速迭代的需要,生产成本之高也严重考验着企业的承受能力,且多个平台的一致性体验并不尽如人意,因此,仅使用一套代码,同时适配多个平台的能力就显得极为重要。
目前,Hybrid、RN、weex、小程序等框架陆续推出,各互联网大厂也在积极尝试跨端开发技术的实践应用,已有很多业务使用到跨端技术,但各个框架各有优劣,且仍然离不开原生开发;而 Flutter 框架推出后,以其性能高,多端平台的 UI 一致性高,及开发调试效率高等强优势,越来越吸引着原生开发者的注意,并成为其首选的跨平台技术框架。
Flutter 是大前端时代的必经之路
近年,京东技术中台也在移动应用跨端开发领域进行了深度探索与实践,JDReact 已广泛应用于京东系数十 APP 的几百个业务内,京东小程序开放平台也于 2020 年 4 月正式发布推广,而备受瞩目的 Flutter,我们早在 2017 年的官方非正式版推出后,即投入调研开发,并在物流 APP 内实现验证上线,其高效的调试效率,极低的 UI 试错成本,以及接近原生的流畅性体验,都给了我们很大的吸引力。2018 年初,我们将现有的混合 APP 进行了一次重构,历时两个月,实现了第一个纯 Flutter APP 正式上线,研发人力缩减 25%,开发效率得到了明显的提升。
在这次重构中,我们也意识到,虽然 Flutter 具有很令人兴奋的优势,但也存在明显的缺点,例如,Flutter 技术生态尚不成熟,开发者初期投入,一般都会面临大量时间投入在框架的基础建设中,人力消耗反而很高。为了避免京东内部团队重复建设,构建高可复用的 Flutter 基础设施,从根本上实现真正的降本提效,京东技术中台成立了专项团队进行 JDFlutter 的研发与建设,专注于 Flutter 基础生态建设,为内部 Flutter 开发者提供包含专业开发工具链、SDK、组件的一站式开发解决方案。
我们的目标:解决实战开发问题,打造畅快开发体验,共建 Flutter 生态。
内容回顾:干货 | 京东技术中台的Flutter实践之路(一)
JDFlutter 全新升级一站式解决方案
JDFlutter 历经 2019 年的发展与积累,以提供混合路由+Flutter 组件+技术支持的方式,已经与京东 App,视频 App,物流 App,到家 App,一号店 APP,7Fresh,掌柜宝,极速版 APP 等数十个开发团队进行交流,并建立了合作关系。期间我们发现,App 开发团队在使用 Flutter 改造业务时,普遍会碰到如下问题,导致开发效率非但没有得到提升,App 容错能力等反而会降低:
Flutter 和原生交互工作量大,需要配置 Android,iOS 和 Flutter 三端的开发人员,提高了开发门槛和人力成本。
Flutter 容器无法共享 Flutter 引擎,打开多个 Activity 时会启动多个 Flutter 引擎,内存开销比较大。
基础组件和通用业务组件较少,需要业务自行封装各种基础组件,且没有一个统一的平台支持组件共享。
Flutter 不支持反射,在 iOS 端无法动态更新可执行代码,线上出现问题,只能重新发版本,没有较好的兜底方案,容错性较差。
2020 年初,技术与数据中台-共享技术部重点投入资源,全面升级 JDFlutter,以 JDFlutter 容器+开发工具+全新组件平台+Demo App+技术社区等矩阵型产品,为开发者提供了一站式移动应用跨端开发解决方案,帮助 Flutter 开发者降低接入及开发成本,助力提升业务效率。
01,容器
容器是我们在操作系统和业务执行逻辑之间的中间层,它隔离了操作系统和应用逻辑的直接联系,也隔离业务和基础组件之间的依赖,让开发者无需关心各个操作系统的差异,只需面向容器 API 编程即可,这样做的好处有以下几点:
1. 统一技术栈,简化工作量:业务开发统一采用 Flutter 开发,无需额外配备 Android 和 iOS 开发工程师,适配的工作全部由容器来做;
2. 便于组件复用:比如收货地址管理的组件,是基于容器 API 开发的,那么同样基于容器 API 开发的 APP 都可以复用该组件;
3. 底层模块可替换,更方便维护:容器对下层模块也提供了统一的协议层,只要上层 API 不变,底层模块可以根据协议来重新实现和替换;
4. 减少包的体积大小:统一 API 之后,开发者不用再去自己依赖第三方插件,大家统一共用容器的基础组件,提高复用性,JDFlutter 容器组件为独立插件,通过注入依赖的方式注入到容器之中,耦合性非常低;在混合开发中,一般 native 工程中都会有相同的功能组件,我们可以将 native 组件注入的到容器中来代替容器中的组件,这样可以做到最大化的减少容器的体积;
5. 业务代码隔离:组件可独立编译调试,容器提供了一套完整的运行环境,每个业务组件可以独立去开发,编译,运行,这样多个业务团队可以并行去开发各自的业务工程,通过 router 的方式实现依赖跳转,避免代码交叉调用,减少代码污染。
02,动态化
动态化作为顺应业务高速发展及低成本试错,实现灵活高效发版和更新的重要手段,近年来显得尤为重要,甚至成为了衡量移动端框架优劣的核心指标,RN、小程序等之所以能被大规模使用,也和支持动态更新,无需发版安装有着一定的关系。
Flutter 本身在跨平台和性能方面都表现卓越,但是由于苹果对于动态代码执行的限制,导致 Flutter 无法实现 iOS 端的动态化,这可能是它的不足之处(主要是苹果的政策原因和技术无关)。经过我们的调研,目前市场上动态化实现的方式有两种,一种是以 Dart 作为 DSL 动态下发的方式来实现布局的动态化,另外一种是用 JS 来开发 UI 生成描述信息,最终由 Flutter 进行渲染。
JDFlutter 在动态化方面也做了一些探索尝试,我们的目标是采用 Flutter 环境进行开发调试,使用动态化框架开发出来的代码既能动态化运行,也能在 Flutter 原生环境中运行,同时不入侵 Flutter 的底层框架,对 Flutter sdk 升级保持很好的兼容性。
本文简单阐述实现思路,后续将单独介绍具体的实现方法。
使用 Flutter 开发环境进行开发和调试程序,发布时采用 dart2js 技术将 Flutter 代码转换成 js 代码,发布到服务端,然后由 Flutter 容器从服务端下载代码,执行 js 逻辑,将 js 渲染的布局信息,传递到 Flutter 层,最终由 Flutter 渲染出来。
03,模块注入
我们在 JDFlutter 封装了一套应用开发所需的基础模块:包含网络,图片,异常,埋点,性能,设备,扫码,视频等业务开发所需模块,模块分为两种类型,一种是基于纯 dart 开发的模块,另外一种是基于 native 封装的模块。根据不同的编译产物我们会注入不同类型的模块来满足不同运行平台的需求,如编译成 web 产物,会注入纯 dart 的网络模块来代替封装的 native 模块。
04,Flutter2Web
体量及规模庞大的线上业务活动,在巨大流量冲击下,可能会面临宕机的风险,类似情况,服务端普遍会通过如集群扩容、多机房部署、限流、削峰、降级兜底等预案进行部署。同样,移动端上线新业务,在未经过大规模验证的情况下,也可能在个别场景出现异常,需要考虑兜底方案,以减少线上事故的发生。
此时除了动态化修复更新之外,我们使用了 Flutter2web 工具将 Flutter 业务转换成 H5,用于降级容灾。JDFlutter 容器抹平了 native 和 web 的 API,在代码不用做改动的情况下,支持将 Flutter 应用转换 web 应用,运行在 JDFlutter 的 webview 中,并提供 js channel 的支持,web 依然可以调用原生能力。
05,iOS 瘦身
Flutter 打出的 ipa 包一般会比较大,先期京东 APP 上线的 6 个 Flutter 业务集成后,致使 iOS 客户端增加了约 17M。为了减少包大小,我们借鉴了字节跳动的做法,对引擎做了改造,将 App.framework 和 Flutter.framwork 的部分数据通过动态下发的方式来实现,同时剥离了资源文件。改造之后,对 Flutter 业务进行再次打包测试,包体积可减少约 28%左右,瘦身效果明显,且随着业务数量的增加,瘦身的效果及收益会更为显著,以下是瘦身方案,后续关于 iOS 瘦身,也会做详细的分享。
06,混合开发
Flutter 与原生的混合开发有两种情况,其一,开发 Flutter 业务的同学,需要和原生做交互,因此需要有 Flutter 和原生的混合编译环境;其二,使用原生 SDK 开发业务的同学,需要和 Flutter 业务一起集成打包,但对 Flutter 透明,无需编译 Flutter 的代码,以减少对 Flutter 编译环境的依赖,我们将 Flutter 编译成 aar 或 framework,放入原生项目中即可,以下为 JDFlutter 混合开发的流程介绍。
07,多团队基于容器的开发方式
容器提供了一套完整的运行环境,实现了业务组件解耦,每个业务都可以独立编译,运行,调试,待到发布时再集成主客户端,业务集成时可通过线上自动完成,这样好处上文已说明,可减少业务组件之间的交叉依赖,同时也可以提升编译调试效率。
08,Pub 仓库
前一篇实践文章中分享了 Pub 仓库的搭建过程,2020 年初京东 pub 仓库做了深度的定制,除了满足基础组件上传和下载功能依赖,还增加了账户认证,权限管理,组件收藏,文档,社区等功能,来完善京东 Flutter 的内部生态,打造更好的技术氛围,当前内部共享的组件数量已达上百个,还在不断增加中,后续我们也会将优质组件开放出来,贡献给外部社区,帮助外部的小伙伴更好地完成 Flutter 基础建设。
09,JDFlutter 全流程支持
为了让业务开发者开发能够更方便快捷地接入的容器 sdk,JDFlutter 提供了配套的开发工具让用户可以一键创建工程,git 仓库,配置依赖的容器 sdk 和工程的初始化模版代码来简化开发者的工作量,同时支持热更新与灰度发布,Flutter 插件发布,在线打包,异常监控,容灾降级等一站式的服务,提供了全流程的支持。
JDFlutter 未完待续
2020 年,正是 JDFlutter 产品化及规模化发展的元年,京东技术与数据中台-共享技术部已经投入大量的核心研发人力,对项目进行重点建设;当前 JDFlutter 的每一项开发任务,都是为了帮助京东的业务研发团队更快速更顺利的实现业务发展目标,不止于此,JDFlutter 未来也会更加开放,以专业的商业化解决方案来帮助更多外部开发者。
我们也和 Google 的 Flutter 的研发团队保持着密切的联系,对技术问题进行探讨和分享,后续对于容器,动态化,Flutter2web,Flutter 瘦身,持续集成,Pub 仓库等方面的最新进展及成果,我们会持续为大家带来专题分享,期待大家的关注与支持。
欢迎加入 JDFlutter 技术专区探讨交流。
QQ 群:1022619726
欢迎点击【京东智联云】,了解开发者社区
更多精彩技术实践与独家干货解析
欢迎关注【京东智联云开发者】公众号
版权声明: 本文为 InfoQ 作者【京东科技开发者】的原创文章。
原文链接:【http://xie.infoq.cn/article/0243c9f6468fb5aa1105619da】。文章转载请联系作者。
评论