Hippy 是腾讯开源的跨端框架,在腾讯内部业务场景中有广泛应用。腾讯视频搜索业务基于 Hippy 2.0 框架开发,在使用过程中发现了一些不便利的地方:动画渲染双端不一致问题;对图片和样式的处理双端不一致现象;没有可用的横滑组件/双列流组件等等。Hippy 3.0 框架从底层实现逻辑进行重新构建,实现了 iOS 端和安卓端双端统一化,标准化和流程的一致性。升级 Hippy 3.0 框架后,开发双端不兼容问题大大减少,开发效率提升,搜索首页实现秒开。读完全文还可以参加惊喜活动抽奖哦!
👉目录
1 前言
2 腾讯视频搜索在 Hippy 2.0 框架上遇到的问题
3 Hippy 3.0 框架升级过程
4 新特性支持与一致性优化
5 Hippy 3.0 应用开发脚手架
6 对 Hippy 3.0 后续版本的期待
7 总结
Native 原生的应用开发虽然体验好,性能高,但是安卓端和 iOS 端各自需要开发和维护一套代码带来了高昂的成本。于是,App 跨端解决方案应运而生。Hippy 是 TDF 端框架(Tencent Device-oriented Framework)子产品中重要一员,为业务提供高性能、跨平台、动态化的跨端解决方案,有效帮助业务开发团队提高研效的同时也可以让业务获得接近 Native 的体验。
腾讯视频搜索业务率先接入 Hippy 框架,目前一套代码同时支持安卓客户端、iOS 客户端和 H5 Web 端,客户端的体验非常接近 Native 体验,并且大大提高了开发效率,节约了人力成本。最近,我们腾讯视频搜索业务成功从 Hippy 2.0 框架升级到 Hippy 3.0 框架,本文将如实还原整个升级过程,希望能够给大家有所启发。
腾讯视频搜索业务是基于 Hippy 2.0 框架进行开发的。上线近1年以来,在使用上发现了一些影响开发效率的问题,总结主要有以下几个方面:
1)在图片的样式处理上 iOS 端和安卓端存在许多不一致的地方,需要兼容处理。比如:图片的圆角在 iOS 端不生效,安卓端生效;需要在图片外多包一层 div,把样式应用在 div 上,这样会增加页面的层级数量;
2)字体的样式也需要多包一层 div,把字体样式应用在外层的 div 上,这样也会增加页面的层级数量;
3)Hippy 2.0 框架上没有可用的横滑组件,需要用 Scroll List View 来做横滑效果,但是,不幸的是,Scroll List View 会存在 OOM 的问题,需要前端对横滑列表的渲染数量做兼容处理。重点提醒:让尽量少的节点数量留在横滑列表中,千万不要把整个列表数据一股脑全部塞进横滑列表中来,否则会使页面的内存消耗激增;
4)在 Hippy 2.0 上做动画也是比较痛苦的一件事情,iOS 端和安卓端的表现不一致,比如缩放过渡效果等,需要做大量的兼容处理,比较影响开发体验;
5)子节点没办法继承父节点的样式属性,比如字体的 Size、Weight、Style 等,要么在每个子节点上再把属性重新设置一遍,要么用很耗时的操作去取这些属性:Vue.Native.getElemCss(this.$el); 这两种方式都有缺点,第一种方法会导致节点的属性过多;第二种方式 getElemCss() 是一个比较耗时的操作,会增加页面的渲染耗时。
Hippy 3.0 框架在今年7月份已经对外发布,通过跟 Hippy 框架团队进行沟通,了解到很多 Hippy 3.0 的新特性,优化升级能够帮助解决 Hippy 2.0 框架使用上遇到的问题,于是我们立马制定了 Hippy 3.0 的升级方案。
Hippy 3.0 的升级对于前端业务逻辑来说是不需要做任何适配修改的,只需要升级 Hippy 依赖包就可以。在发包方面,不同的团队,接入 Hippy 的时候,发包的方式不一样,使用的离线包平台也不一样。腾讯视频搜索团队接入的是 Shiply 离线包平台。如果大家用了离线包,最好 Hippy 3.0 框架跟 Hippy 2.0 框架用不同的离线包包名,不要用同一个包名,否则后续的升级和维护会非常容易混乱。
虽然 Hippy 3.0 框架渲染层基于 FlattenUI 已经在渲染耗时方面有很明显的优化效果,但为了进一步提升页面打开的速度,我们和 Hippy SDK 小伙伴一起成立了优化专项小组,针对搜索场景对页面打开耗时做了更全面深入的分析。经过大家一个多月的努力,挖掘并完成了多项优化实践,并取得了不错的优化效果。下面给大家分享一下对于耗时关键点的分析和一些优化方法,希望对后续接入 Hippy 3.0 的小伙伴们也有所帮助。
1)Hippy 引擎预加载,并且在预加载的时候提前读取首页缓存数据。具体的流程如下图所示。
从图中可以看出,Hippy 引擎预加载,能够节约 Hippy 引擎启动和加载离线包资源的时间。提前读取首页缓存数据,可以节省读取缓存的耗时和解析数据的耗时。读取缓存数据的前提是应用页面有缓存数据可读。如果是一个页面数据未知的页面,例如搜索结果页的数据是需要用户先输入搜索关键字才可以得到页面数据,则不可以提前读缓存数据。通过这一步,我们的耗时直接缩减了26%左右。
2)接入 JSI,通过 JSI 来调用 JSAPI,提升页面性能
我们在对页面性能进行分析的时候,发现很多 JSAPI 调用比较耗时,特别是对页面渲染有依赖的 JSAPI,如果它耗时比较久,会影响到页面的渲染耗时。Hippy JSI(JavaScript Interface)模式提供了一种无需经历编解码(序列化)过程的跨 VM 互相调用的解决方案,使得 JS 可以和 Native 客户端直接通信,并且可以定义接口为串行的调用方式,屏蔽掉了接口异步读取的不确定性,从而使耗时比较稳定。我们在本地对同一个 JSAPI 接口分别进行正常的 JSBridge 调用和 JSI 调用,分别测试5次取平均数,对比数据发现,对 JSAPI 通过 JSI 方式调用,比进行正常的 JSBridge 调用,耗时能够缩减90%左右,缩减幅度非常可观。
3)SDK Hippy-Vue 优化
在 Hippy 3.0 的重构中,SDK 同学发现 Hippy 在节点 CSS 样式计算耗时占用比较大,所以 Hippy 3.0 版本对 CSS 算法和 CSS 计算频次分别做了优化。
(1) CSS 算法优化
Hippy-Vue 项目的 CSS 解析算法,早期版本是使用 NativeScript-Vue 框架的 CSS 解析算法,是纯 JS 实现的。那这个 CSS 解析算法本是不是不太高效呢 ?通过对比业界其它 JS 版本的 CSS-Parse 方案,发现整体性能差距不大,主要原因是这些算法是按照通用 W3C CSS 规范实现的,按照规范实现的算法各自的方案整体思路接近,因而性能差距不大。
不过,Hippy 作为一个 App 动态化框架,其实只实现了 CSS 的子集,业界其它框架如 React-Native、微信小程序等也仅实现了 CSS 的子集,并未实现属性选择器等高级 CSS 能力(可能是性能的考量)。因此,我们可以考虑对 CSS 的高级能力做一些舍弃,对 Hippy 所定义的 CSS 子集部分重新实现,从而更好的优化算法流程。
一个典型的例子是 Vue Scoped CSS,Scoped 在 Vue 的编译期会转换为属性选择器,而属性选择器因为有属性权重计算,解析的算法时间复杂度是比较高的。Scoped 的设计目的是为了隔离属性,一种简单的思路是参考 CSS-Module 方案,在编译期找出被 Scoped 标记的属性,给属性名加上后缀,这样属性在运行期解析时会用 Class 选择器的方式去处理,Class 选择器解析逻辑是相对简单的,从而降低算法的时间复杂度。
通过一系列 CSS 算法优化后,iOS 整体耗时下降 18%,Android 整体耗时下降 10% ,做到在支持 Scoped 等特性的同时又有效解决了性能问题,同时,SDK 的同学也在探索 C++ 版本的 CSS-Parse 方案,从根本上提升解析性能。具体效果如下图所示。
(2) CSS 计算频次优化
除了上面提到的 CSS 算法耗时,还有比较多场景会产生冗余的 CSS 计算,而导致耗时增加。针对这个问题,SDK 内部做了如下两个优化:
第一:CSS 缓存优化。
对已经计算过的 CSS 结果,做计算缓存;
对无须计算 CSS 的场景,直接跳过计算;
优化效果:应用 CSS 缓存优化,搜索结果页打开耗时减少了 30ms 左右。
第二:Event 调用链优化。
在 Hippy 2.0 的事件模型中,事件是作为节点的一个 boolean 属性,通过设置 true/false 来标记是否注册事件,并把事件回调注册在全局 map 中。 因而事件注册和属性更新流程是耦合的,每次注册/销毁事件,会同时触发节点属性更新 和 CSS 计算,造成性能损耗。
在 Hippy 3.0 中,重构了事件模型,属性是作为方法直接挂载在节点上,把属性注册流程和属性更新流程分离,从而减少了因注册/销毁事件,而产生的冗余节点属性更新和 CSS 计算带来的性能开销。
优化效果:搜索结果页能减少 300多次节点的属性更新,页面打开耗时减少30ms左右。
搜索场景接入 Hippy 3.0 框架后,配合系列性能优化手段,11月份上线以来,首屏渲染耗时和结果页的渲染耗时都呈现了下降趋势,优化效果很明显,具体趋势图如下:
1)Hippy 3.0 动画驱动机制统一下沉到 C++ DOM 层来实现,很好的保证了双端动画的一致性,有效解决了我们一直以来在 Hippy 2.0 由于双端动画不一致需要做大量兼容处理的问题。
2)在 Hippy 3.0 上,双端都可以有十分方便的横滑组件可用,解决了我们在 2.0 使用 Scroll List View 来做横滑效果的痛点。
3)Hippy 3.0 在 SDK 层面实现图片样式支持的双端统一,我们也不需要再为了实现圆角效果,单独在图片外多包一层 div,进一步减少页面节点层级与复杂度。
4)支持 Scoped CSS。在 Hippy 2.0 中,是不支持 Scoped CSS 的,需要自己编写 Webpack Scoped CSS 插件来支持;在最新版本的 Hippy 3.0 中将会支持 Scoped CSS,不需要自己写插件来兼容了。
5)支持子节点自动继承父节点样式属性。在 Hippy 2.0 中不支持子节点自动继承父节点样式属性,所以每个子节点都需要自己设置一遍,存在很多冗余属性的设置,在 Hippy 3.0 上可以把通用的样式属性放到父节点上,子节点自动继承父节点样式属性,不用再进行每个子节点的复杂样式设值了。
腾讯视频前端搜索团队目前有很多应用都是基于 Hippy 框架进行构建的,例如搜索首页,搜索结果页,筛选系统,榜单系统,找片系统,明星装扮系统,家庭版 MVP 等。在对系统进行构建过程中,我们通过对系统的框架进行提取,通用组件进行提取,流水线进行提取,构建了基于 Hippy 3.0 框架的应用开发脚手架:generator-athena。利用脚手架进行 Hippy 框架应用开发,能够大大提高开发效率。
Generator-Athena 开发脚手架的组织结构图如下图所示:
本脚手架集成了 Shiply 离线包平台,以及离线包平台的打包脚本;集成了蓝盾流水线的相关配置;并且提供了11个通用组件,能够让大家快速开发大部分应用页面。
同时,我们在页面文件中提供了实例文件,规范了文件的命名规则和变量的命名规则,以达到 Web 端、小程序端和 App 端多端互相转换的命名规范要求。
之前一直有看到其他 Hippy 接入方如K歌团队,浏览器团队分享更换 Hermes 引擎后带来不错的性能提升,但通过了解后发现,他们都是在自己独立分支进行改造接入,并没有合入 Hippy 官方的代码仓库,也就是说他们的改造方案是无法无成本平移到其他接入方的。
针对这种情况,我们跟 Hippy SDK 的同学沟通后了解到,Hippy 3.0 对 JS 引擎的封装层 NAPI 也做了重构,能够支持不同 JS 引擎的接入和切换。而且 Hermes 引擎已经完成了80%的适配工作,并在 SDK Demo 跑通了,也就是说未来 Hippy 官方将在 3.0 版本正式支持 Hermes 引擎的接入。
我们也尝试提前在腾讯视频搜索场景接入 Hermes 引擎来检验效果。经过和 Hippy SDK 同学一起努力配合,在解决了 Hermes 引擎加载业务 Bundle JS 的一些适配问题后,终于在视频 App 里面基于新引擎的搜索页面能跑通了。切换 Hermes 引擎后的性能对比数据如下:
说明:测试的时候,为了避免网络拉取数据的波动影响,通过本地 hook 数据录屏分帧的方式对搜索首页和结果页打开耗时分别进行了对比测试。
从 iOS 的测试结果来看,不论是有预加载还是没有预加载,使用了 HBC 的 Hermes 对比 JSC,在搜索首页和搜索结果页都有近40%的性能提升,和之前在浏览器那边了解到的数据来看页基本是相符的,iOS 端 Hermes 引擎能带来较大的性能提升。
从 Android 的测试结果来看,在无预加载的情况下,使用了 HBC 的 Hermes 对比 V8,搜索首页有 11% 的提升,搜索结果页有 4% 的提升。在有预加载的情况下 Hermes 反而落后于 V8,所以这里就没有再列举数据了,整体来看 V8 的性能还是不错的,针对 Android 一些处于内存考虑无法做预加载的场景可以考虑使用 Hermes,如果有预加载的场景还是继续使用 V8 可以获得最好的性能表现。
从 SDK 同学那里我们也了解到 3.0 后续版本规划的一些非常值得期待的新特性:
1) Android 端瀑布流组件升级,支持滚动列表更多的布局方式,提供更稳定更流畅的体验;
2) Performance API 与 Aegis-Hippy Sdk 升级支持更加完善的前端性能监控与上报;
3) Animation API 与 transformOrigin,对动画能力支持更加完善;
4) Intersection Observer API,支持页面任意节点做曝光监控;
5) font-face 支持下载远程自定义字体。
腾讯视频搜索业务是第一个吃 Hippy 3.0 框架这个“螃蟹”的业务团队,在整个 3.0 升级过程中,通过和 Hippy 框架团队的紧密配合,不但解决了之前很多 2.0 开发过程中遇到的痛点,也成功实现了我们下半年性能优化的挑战目标,最终品尝到了Hippy 3.0框架这个“螃蟹”的鲜美。
最后,也欢迎大家在升级 Hippy 3.0 的过程中,随时跟我们交流心得,探讨问题!
-End-
原创作者|熊才刚