饿了么端618、国庆、双11、双12等大促会场基本上会标配底部导航,在之前一般H5容器中底部导航是前端实现,每次点击会场底部导航的tab,都会重新启动一个流动页面笼罩在下面,即便之前关上过的tab也都要从新创立和加载,体验不佳,且H5也不能很好的联合Native能力做进一步的体验和性能优化。
作者:逍菲、崖松、子伦
饿了么端 618、国庆、双11、双12等大促会场基本上会标配底部导航,在之前一般H5容器中底部导航是前端实现,每次点击会场底部导航的tab,都会重新启动一个流动页面笼罩在下面,即便之前关上过的tab也都要从新创立和加载,体验不佳,且H5也不能很好的联合Native能力做进一步的体验和性能优化。
通过调研发现手淘PHA框架可解决上述痛点问题,PHA容器底部TabBar为Native渲染,tab点击时底部bar不会重建,tab对应的webview在整个PHA容器中也能够平滑过渡、无缝切换,无需另起容器。且加载过的tab流动页面Webview会常驻内存,当再次拜访时会间接切换至前台,更靠近native体验。
在去年 618、国庆、双11和双12大促中,联合饿了么业务个性又陆续落地了一些特色优化伎俩,带来了更好的性能体验和业务成绩。
双十一上线成果
成果视频查看请点击:饿了么双十一 PHA 会场实际
老容器和pha容器比照。其中左侧为老容器会场,右侧为pha容器会场。
PHA 简介
什么是 PHA,PHA 全称 Progressive Hybrid App,是晋升 Hybrid 体验的一种新框架,提供了一些 Native 同层组件以及渐进式加强策略来创立 Hybrid APP 利用,让这些利用具备与 Native 雷同的用户体验。
- PHA 应用了 Web Application Manifest的配置并且对配置进行了性能扩大
- 每个 PHA 利用都会启动一个 App Worker,Worker 是独立于以后页面运行在客户端里的一段 JS 脚本。可在 Worker 中定制业务逻辑,如基于 LBS 申请底部Tab展现的数据列表
- 利用下能够有多个页面,每个页面的默认渲染引擎是 WebView
- 每个页面中 PHA 提供了像下拉刷新、页头等 UI 能力,都能够通过在 Manifest 中定制
- 针对利用 PHA 还提供了 Tab 容器、Swiper容器、启动屏等 UI 能力和预申请、离线缓存等性能优化能力,可通过在 Manifest 中配置实现
pha架构图
饿了么接入计划
本地生存跟淘宝等业务次要的区别为前者强依赖LBS属性,包含底部 Tab、商品、品牌等数据的召回。因而须要在用户关上PHA框架时,执行定位并加载对应的底部 Tab、顶部横滑数据后,动静组装出对应的manifest.json 数据来渲染PHA,整体架构图如下:
架构图
B端链路
墨斗平台依赖天马源码页面服务来创立会场框架,沿用墨斗数据搭建来配置底部 Tab 和 顶部Swiper 的数据,实现定投,次要流程如下:
注:“墨斗”是一个模块搭建平台,“天马”能够提供根底搭建服务。
数据搭建
数据搭建是墨斗中提供的数据多排期定投能力,配置定投并公布后可失去以后配置的惟一资源位ID, 业务可通过异步接口取得配置数据。
会场框架工具
新增会场框架工具,工具提供了会场框架创立、公布及编辑能力,创立并公布框架后即可失去框架投放链接。
C端链路
C端链路由客户端联合前端实现,次要蕴含以下3局部:
1、客户端PHA框架:集成了 Tabs 容器、Swiper容器、启动屏、Appworker、预加载等框架外围能力
2、源码模版页:作为PHA框架的入口,同时提供 PHA 失常加载入口 (native.xtpl) 和降级入口 (web.xtpl)
3、AppWorker 服务:能在框架渲染前有机会依据业务诉求定制 manifest,包含头部横滑容器的 UI 定制,事件处理、埋点等
整体加载链路图
客户端接入革新
路由层
革新饿了么路由层,减少pha入口,并在入口处减少native的降级策略、灰度管制等逻辑。
适配器:native导航头适配
因为剥离了手淘的ui库,饿了么须要自行实现导航栏的: 显示、暗藏、各类主题、滚动变色、title设置、logo设置、事件回调、降级跳转等,此外双端也提供了一些导航头、状态栏等公有jsapi供前端进行调用。
iOS端通过PHANavigationBarProtocol实现对应办法,Android端以零碎Toolbar为根底,定制饿了么的TranslucentToolbar,以Fragment的模式嵌入到PHA容器Activity中。
下图是native端导航头,title反对设置文字、加载图片,导航栏主题反对通明、红色:
文字&图片导航栏
下图是light和dark格调的状态栏:
light&dark状态栏
适配器:图片加载适配
饿了么iOS端因为本人保护了图片库,须要对图片加载进行适配,实现PHAImageLoaderProtocol及其图片加载相干办法。
淘系依赖剥离
饿了么对于包大小有严格的管制,对于新引入的二三方库审核严格。饿了么端接入pha较早,晚期版本中存在额定的手淘依赖,且有些性能饿了么临时未用到,或已有相似的实现计划,因而须要对局部手淘依赖库进行剥离,对不须要的性能进行剪裁。
安卓剥离的间接依赖库约20个,如:直播库、公共资源库、ui库、compat库、启动框架库、atlas等,总大小约:7.2M+,波及文件改变个数:100+
注:目前安卓最新的官网2.0版本已剥离了这些依赖,大大的赞!iOS端在一接入pha时依赖已根本剥离,无需大的革新。
前端接入革新
框架服务
1、源码模版:作为PHA框架的入口,同时提供 PHA 失常加载入口 (native.xtpl) 和降级入口 (web.xtpl)
- 失常入口:基于平台创立会场框架时录入的数据生成manifest 半成品,后果中蕴含 AppWorker 地址,创立框架时的配置信息等,客户端执行 AppWorker 文件后,启动PHA框架渲染
- 降级入口:为不反对PHA的低版本或PHA创立失败时提供对立的降级解决,用一般H5容器关上投放链接中的 downgradeUrl 地址实现降级,保障业务可用
2、AppWorker 服务:能在框架渲染前有机会依据业务诉求定制 manifest,次要提供如下能力
- 定位、申请底部bar、顶部swiper数据
- 头部横滑容器的 UI 定制、事件处理
- 和PHA的事件、音讯解决
- 构建最终的 manifest 文件
- 启动框架渲染
- 埋点等
会场链路
1、页面solution、根底util、componet 革新
2、多个模块革新
- 通明头模块:之前通明头是H5联合Native来实现的,业务定制能力绝对较弱,为了解决这个题,针对PHA容器实现了纯H5版的通明头模块
- 底部导航模块、搜寻模块、分享模块:兼容PHA 和非PHA容器
埋点革新
PHA框架提供一套埋点API,客户端和前端需依据本人的埋点计划进行适配革新,统计和上报口径跟非PHA下会场埋点保持一致,次要有以下两点:
- 需在每次切换页面时上报PV,包含曾经浏览过的页面,如Tab A 切到Tab B 再切到Tab A 时,在最初的Tab A 页面须要触发PV上报
- 底部 Tab 或顶部 Swiper 容器切换不同 Item 时上报点击埋点
性能优化
饿了么端pha容器加载流程次要为下图四个阶段,针对不同阶段可进行对应的性能优化伎俩。
- pha容器阶段:半成品manifest和worker可进行预取或缓存优化;残缺manifest数据申请组装阶段可进行经纬度的预取和接口的预申请;
- webview阶段:webview可进行预初始化,主文档加载能够用模版化形式进行优化;
- 业务阶段:针对业务js、css资源可进行资源离线和缓存,对罕用js资源可进行内置;对业务接口数据可进行预申请;预热和预渲染。
官网PHA框架优化伎俩
pha框架自身提供了manifest预申请和缓存、html模板化、离线资源存取、内置Js预渲染等优化伎俩。
以iOS端双十一会场为例,应用manifest和worker预取,优化容器创立工夫200ms以上。
饿了么端特色性能优化
PHA webview预热
关上pha首屏页面和切换tab时须要执行容器创立和主文档加载,有较长时间的白屏,体验不佳。预渲染页面无疑是性能成果最佳伎俩,但一方面会造成资源节约,另一方面也会带来很大的内存压力,不能随便滥用,后续若能和端智能更好联合或者能力更好的施展它的价值。
饿了么端对首屏外的tab采纳了预热计划(预热页面最大个数可配置),来打消tab切换时的白屏工夫。预热和预渲染的不同点为:预热在离屏阶段拿到主文档后不发动首屏接口申请。在首屏页面渲染实现后,将剩下的底部和顶部item对应的webview都预热并缓存好,当用户点击对应tab时再生产webview进行上屏操作,具体实现复用pha/preload子模块链路并进行了一些革新,参考了TSchedule的预渲染逻辑。次要流程如下图所示:
优化前后链路比照:
上面具体展现预热成果(左侧为未开启预热,右侧为开启预热状态):
成果视频请点击查看:饿了么双十一 PHA 会场实际
业务接口预加载
会场页面的首屏接口耗时较长,局部甚至达2s以上,为了缩短页面加载耗时,对首屏接口进行预申请。思考到饿了么端之前已通过TSchedule反对了接口预申请的能力和包大小问题,因而决定不引入pha的prefetch模块,而是借助饿了么现有能力对pha进行data prefetch的适配化革新。
由客户端同学提前公布orange(开关配置公布平台)预申请配置,pha会场在首屏路由、底部tab切换、顶部pageheader切换时提前触发接口预申请,也提供jsapi供前端自行调用预申请,优化成果显著,目前曾经是饿了么端会场业务必备优化项。
(1)、首屏webview加载前网络数据异步预申请
(2)、启动前路由阶段网络数据异步预申请
(3)、tab切换webview加载前网络数据异步预申请
(4)、通过jsbridge在webview加载前网络数据异步预申请
残缺manifest数据申请优化
本地生存业务多对定位有强依赖,对于会场业务目前只能先返回半成品manifest文件,在worker中调用端上jsapi拿到经纬度后发动接口申请,获取残缺manifest相干数据进行组装;对于非会场的单页面业务进行接口申请时也大都须要经纬度信息。
经纬度预取
形式一: 将经纬度信息注入半成品manifest(针对须要pha worker对半成品manifest文件进行解决的业务场景)
在回传给前端的manifest半成品json中,追加上首页缓存的经纬度数据,省去一次jsbridge调用耗时。优化前后流程对比方下图所示:
追加的经纬度信息模板:
形式二: 在入口链接处传入经纬度(针对无需pha worker的场景)
大多单页面业务在一开始就能获取到残缺的manifest数据,不须要worker进行额定解决,也就无奈间接通过形式一取得注入的经纬度信息,因而咱们采纳了另一个计划,给pha入口链接(manifest url)拼接经纬度参数,并通过pha参数透传的能力将其拼接到H5内页的链接上。具体流程如下:
残缺manifest数据接口预申请
在worker获取经纬度后,会应用页面id、资源id和经纬度发动一个接口申请,获取残缺manifest所需数据(pages、tab等),数据返回后拼接成残缺manifest数据,而后调用jsapi告诉端上更新manifest,进行tab和页面的加载,此接口耗时大略200ms左右。
通过在路由阶段预申请此接口来进行优化,因为接口所需的页面id和资源id针对同一大促会场投放期间根本不会扭转,因而提前公布的预加载配置将这两个id间接设为固定值,而经纬度在预申请发动时动静获取。
此性能上线之后通过两个版本的比照,首屏耗时整体缩小约150ms。
稳定性
降级
PHA框架渲染前的任何一步出错可能导致框架初始化失败,为实现同一个链接投放到饿了么新老版本,并保障业务在各种异样场景下可用,需做到无缝降级到H5容器,流程如下:
预案
在整个双十一大促开始前,针对pha会场可能呈现的各种异常情况进行了预案的录入和演练,例如:会场降级,预热敞开、接口预加载敞开、manifest预取敞开等,在平安团队和测试团队同学的独特反对保障下,pha容器会场在大促期间运行稳固,未呈现任何重大故障。
监控和报表
在dp2监控平台构建了manifest命中率监控、离线资源命中率监控、降级监控、性能监控、预热命中率监控、首屏耗时监控、容器内webview加载耗时监控、白屏监控等相干报表。
此外手淘目前在建设容器大盘,ios端曾经初步进行了接入,期待大盘后续例如告警,二方业务数据展现等建设。
总结和瞻望
通过pha框架的接入及一系列的优化伎俩,双端优化首屏耗时缩小650ms左右,打消了切换tab时的白屏工夫,晋升了饿了么端大促会场的用户体验,同时也促成了业务数据的晋升。
据经营侧数据统计,去年双十一主会场底部导航Tab的曝光点击率,相比国庆大促正式期晋升超过50%。自618大促正式期试点PHA以来,新底部导航点击率持续上升。
后续前端需解决拼链接的问题作为常态化的产品能力反对各业务场景应用,端侧也将进一步摸索其余的优化计划,比方: Tabbar直出渲染、pha容器Fragment化、quickjs引入等。此外除会场业务,饿了么端超会局部业务也进行了pha投放,获得了一些性能上的收益。
冀望将来饿了么所做的优化点能给大家一些启发与思考,服务更多适合业务,进一步晋升用户体验。
关注【阿里巴巴挪动技术】微信公众号,每周 3 篇挪动技术实际&干货给你思考!