大前端团队对接全集团业务部门,如何既好又快地交付需求是团队一直努力的目标。随着业务不断发展,摆在我们面前的效率问题也越发严重,这其中主要是开发效率和发布效率。
先说开发效率,不同事业部产品有各自的 UI 风格样式和交互流程,功能类似,但是彼此不能复用,成倍增加了开发工作量。另一方面由于历史原因,开发模式陈旧,非常依赖 iOS 和 Android 双端原生开发,跨平台开发能力薄弱,开发资源安排不太合理。
其次发布效率,事业部独立运营,各自的上线和运营计划难以协调,客户端的发布窗口非常密集,甚至一周双发。需求功能要求能在短时间内定向覆盖或全量覆盖用户。传统的 APP 发布方式,尤其iOS发布,由于包含提审时间和苹果固定灰度周期,整个流程非常漫长,无法满足业务方需要。
如何提升开发和发布的效率呢?我们准备从技术升级和流程管理两方面提效来入手。
针对上文提到的UI风格不统一,开发模式陈旧,上线覆盖慢等问题,我们针对性地提出了三步走:
标准化,规范基础和业务组件,统一交互设计,增强复用能力。
跨平台开发能力的增强和建设自主动态化发布平台。
配置代替开发,建设搭建化平台。
标准化
在实际工作中,以货源详情为例,卸货路线信息的展示,不同事业部的 UI 设计完全不一样,看起来甚至不像是一个 APP。某些极端情况下一个需求需要同时改多处,工作量加倍。这是之前的设计:
我们发现,如果能将类似功能标准化,推动各个事业部的设计统一,工作量会大幅度减少。
在与各个事业部的沟通中,我们了解到他们并没有差异化的需求,造成差异化的原因是没有标准来参考,于是按照自己想法设计和试错。自己成功的经验或者失败的教训也没有办法共享。综合看来,弊远远大于利。
为了改变这一现状,我们联合平台部门收集各个事业部需求,推动标准化建设。
货源详情标准化
比如上面提到的装卸货信息,最终我们推出的组件标准如下:
不仅针对单个组件,页面框架也有了统一标准:
将页面以功能组件为单位进行拆分,每个功能组件标准化。面对不同业务场景,服务端返回不同组件和配置等渲染信息,客户端基于这些渲染信息来绘制页面。在标准化之后,客户端只需维护很少的渲染逻辑,大部分业务逻辑由服务端收归。以货源详情为例,客户端和服务端人员投入比降到了 1:7。
发货标准化
同样,我们在核心的发货场景也推动标准化。
当不同业务产品需要对于发货流程调整的时候,通过简单配置,我们不仅可以满足他们的定制化改动,同时在组件化框架的约束下,保证了平台的统一交互和品牌认知。
跨平台和动态化
当标准化收尾后,为了进一步降低开发成本,我们开始深入研究跨平台开发。业内跨平台开发有两个方向,一个是底层技术跨平台,比如通用的网络库,存储,日志等等,另一个是上层业务使用前端技术跨平台开发。我们面临的现状是底层相对稳定,迭代较少,上层业务改动较多。所以对我们来说跨平台开发收益较大的是使用前端技术让业务开发从双端变单端。
前端技术跨平台开发最被广泛熟知的是H5开发,但是由于性能和用户体验的原因,我们选择更加接近原生的技术方案。于是React Native成为我们的第一选择。
MBRN
MBRN是我们基于 React Native 封装的跨平台开发框架,也是我们团队最早开始研究并使用的跨平台技术,使用也最广泛。目前支持了主业务的多数核心页面,涵盖详情、表单、列表等大多数UI场景。期间我们大致经历了3个主要阶段。
1.0尝鲜
从0到1,搭建RN开发环境,客户端同学学习前端开发,并最终在订单模块实现了0的突破,稳定上线,解决了iOS的动态性不足问题。
2.0开拓
更多模块开始尝试RN开发。App整体动态能力增强,开发效率获得提升。RN小组开始逐步丰富基础组件库和方法库,用于支撑更多业务场景。与此同时,开发工具和开发环境也在持续优化,更多同学开始加入RN开发,上手也越来越容易 。然而,在这一阶段,随着使用场景增多,MBRN开始暴露其性能和稳定性问题。
3.0进阶
针对出现的问题,我们在不断完善RN框架的同时,提出了一系列优化手段,包括拆包合包、全局单例和预加载等。同时我们建立起来了稳定性指标,并以此打造了监控告警体系,对于异常、白屏做到了分钟级告警,遇到问题之后使用ABTest和发布回滚等手段及时止血。为了满足我们自身的动态化需求,我们在应用层面又开发了全局动态化弹框系统,RN动态路由方案等等。
至此,MBRN支撑了从发货、货源、下单、成交订单等主流程关键业务,稳定可靠的前提下保障快速迭代。
Thresh【动态化 Flutter 框架】
MBRN基本可以满足我们的动态化需求。然而在使用过程中,我们发现了一些弊端。比如两端一致性还是无法保证,同样的组件iOS和Android上体验不一致,甚至在一端上存在功能缺陷,开发人员不得不进行二次开发,这一定程度影响了开发效率。甚至一些组件存在性能和稳定性问题,开发人员不得不使用Native组件重新封装。
于是,当我们看到保证了高一致性,高性能的Flutter的时候,我们觉得这可能是另外一个能帮助我们达成目标的方案。在研究了Flutter的基础原理,并参考了业内的一些实践之后,我们按照自己的理解,为了满足自身的动态化需求,完成了自己的动态化开发框架,Thresh。
Thresh在业务层使用 TS 作为开发语言进行开发,APP运行时,JS引擎动态解析JSBundle,并构建页面, 经Native将序列化后的页面结构由JS层传递给Flutter层,并最终转换成Flutter组件渲染。
大致架构如下图:
整个框架包含:
JS-App在Flutter层的构建渲染模块
消息表和事件通信模块
基础UI组件库
开发调试工具
...
该框架具备完全动态性、高性能、高一致性。目前已经在内部十多个页面进行了应用,每日近千万页面PV,异常和错误率低于10万分之一,在业务支撑和稳定性上都基本满足了我们的需求。该项目即将开源,敬请期待。
升级平台 XRay
保障功能的动态升级,离不开升级平台 XRay 的建设。XRay 目前支持了:
提供平台级别统一的离线资源管理,包括更新、回滚、加载策略。全面兼容了上层的多个技术栈,包括 MBRN、Thresh、DaVinci、离线 H5、Android 插件。
客户端稳定高速下载,高成功率(iOS:99%,Android:96%)。
支持白名单、百分比等灰度方式,支持柔性自动梯度放量。
业务包覆盖量分钟级监控,覆盖过程的异常监控,出现问题之后的分钟级回滚。
不仅支持单个业务的升级,还支持存在依赖的多个业务组合升级。组合发布示意如下:
最终,大前端围绕跨平台和动态化大致形成了如下的架构:
在动态化技术栈上,我们有基于RN封装的MBRN,有基于Flutter渲染的Thresh框架,本地H5方案,Android端插件化方案,以及后续章节将要介绍的搭建化框架。
依托XRay动态升级平台,使用这些技术框架实现的业务需求可以自主更新而不依赖APP发版,强有力支撑了业务迭代。
与此同时,我们的质量和运营体系提供了业务监控告警和数据分析能力,出现问题之后及时上报,帮助研发及时控制风险。
至此,跨平台开发能力和动态化能力不仅让我们能以更少的人力投入支撑同样多的需求,也帮助业务快速上线,提高了开发和发布效率。
搭建化
当我们完成了双端开发变单端之后以及动态化发布之后,我们还在继续思考可能的更好方案。
不管是 MBRN 还是 Thresh,由于少不了前端技术跟 Native 的通信,性能的损失是客观存在的。
那性能能不能再好一点,能否直接将原生开发动态化?
单端开发毕竟还存在开发,能不能配置代替开发呢?
基于这些思考,我们提出了完全基于 Native 实现的搭建化解决方案。
DaVinci【像写 PPT 一样搭建 APP 页面】
通过一个页面配置平台,进行可视化拖拽,生成页面预览。基于平台生成的页面描述 DSL,客户端使用 Native 组件渲染页面,并支持常见交互和逻辑。
在 UI 组件规范化了之后,利用已有组件快速搭建新页面,极大地提升了开发效率。
在实现的过程中,主要解决了2个关键技术点:
三端一致性保证
实现了一套类XML的DSL,描述UI展示,支持前端、iOS、Android三端。举个货源卡片的例子:
通过配置平台拖拽生成的DSL类似这样:
动态逻辑能力
如果不能执行一定的动态逻辑,这套框架使用会非常受限。这里我们复用了Thresh的JS执行环境,让DaVinci能依赖JS执行动态逻辑,执行完之后传递最新的ViewModel到Native,驱动页面更新。
更多细节,包括模板管理、HotReload、高效发布,这里不详细展开,后续的系列文章会有介绍。
目前DaVinci平台已经在个人中心页使用。在使用过程中,开发效率提升一倍以上。同时我们也在不断完善,进一步拓宽其使用场景。
技术架构的升级,极大地帮助我们提升了开发效率。然而光靠技术解决不了所有问题,高效的管理流程同样必不可少。
我们目前保持着一周两次的迭代节奏,内部称之为“动静结合”。
动:每周 1~2 次动态升级
静:月度 APP 班车版本
静态班车版本一般情况下5~7天全量发布,而动态升级发布24小时内即可全量发布。
经过我们过去不断的动态化重构,目前大部分业务需求都可以通过动态升级的方式来发布。在实践过程中,甚至一些需求可以做到周一评审周五线上全量,从需求提出到上线做到了不跨周。
这样的节奏对于客户端而言是非常有挑战的,一方面离不开技术架构的升级,同时相应的流程管理和工具支撑也非常重要。
需求管理
1.发版负责人在版本日历上创建发版计划。
2.产品录入需求并关联到发版计划,制定需求负责人。
3.版本日历上的发版计划可以汇总关联过来的需求,生成发布看板追踪需求健康程度。
4.开发人员可以在需求详情页面可自动创建开发分支,开发完成后可自动合入发布分支。
5.需求相关的发布分支推导涉及的改动代码,生成动态升级组合发布明细给 XRay发布平台用于升级。
通过上述关键流程,我们跟踪每个需求从创建到上线的各个环节。在发布过程中依赖发布看板将每个需求的风险点直观可视化出来。在关键时间节点,可以将以此发版计划从需求到最终发布的升级包推导出来,帮助测试人员完成相关工作。
代码管理
为了满足动静结合的发布形式,分支管理一度让开发人员非常头痛。
开发过程,一处改动,需要合入静态版本分支和动态升级分支。
如果下一个班车版本迭代进入开发,改动需要继续合入后续静态版本和动态升级分支。
开发人员对于这个流程感到恐慌,操作很繁琐,体验很差,而且风险极高,一次漏合就可能导致线上问题。
那如何给开发人员减负呢?
当我们把规则细化后,我们发现繁琐的偏机械的行为是可以通过自动化手段来帮助我们完成的。经过抽象分析,我们得出了如下图的流程:
开发人员从自己的 feature 分支合一次代码。
工具自动同步到当期的 master 分支和当期的静态和动态分支。
工具自动同步到下一期的 master 分支和所有的静态和动态分支。
以同时开发两个静态版本,每个静态版本对应一个动态升级为例。比起之前人工操作,自动化不仅降低了75%工作量,而且保证了正确性。最终当我们把这套代码管理自动化流程收归到了发布平台后,也得到了大家的广泛欢迎。
至此,大前端效率提升实践已经介绍完毕。我们发现了开发和发布两个方面的效率问题。通过推动标准化,使用跨平台动态化技术开发,搭建化开发,配合发布流程,提升了整体效率,满足了业务线需求,也取得了不错的结果。
对于我们使用的技术和流程管理感兴趣的话可以继续关注我们后续文章的详细介绍。
作者简介:
章伟:满帮移动端技术专家,大前端业务中台移动端负责人,负责移动端业务中台能力建设、跨平台开发和移动端持续效率提升。之前就职于腾讯微信团队,从0到1参与了多个平台微信客户端的开发和持续优化,对于移动端开发有深刻理解和丰富经验。