起点海外版 Hybrid App-内嵌页优化实践

avatar
前端工程师 @上海阅文信息技术有限公司

本文作者:刘文涛

原创声明:本文为阅文前端团队 YFE 成员出品,请尊重原创,转载请联系公众号 (id: yuewen_YFE) 获取授权,并注明作者、出处和链接。

今年年初我司开启了起点品牌的海外之旅,名为「 Webnovel 」。

目前 PC / M站 / App 三端都在快速的迭代中。而其中起点海外版 App 是基于 Hybird 技术进行开发的。作为起点海外 Hybird App 中内嵌页的前端开发,从 1.0.0 版本的陌生,到最近发布的 2.0.0 版本的娴熟,海外版内嵌页的开发方式一直都在改进,力求最大程度的接近 Native App 的页面性能和用户体验。

Webnovel App 页面截图

在开始讲解起点海外版 App 中内嵌页的具体实现以及优化之前,让我们先来了解下整个 Hybird App 实现的具体方案。

一、Hybrid App 实现方案

1. 什么是 Hybrid App ?

Hybrid App(混合模式移动应用)是指介于 WebApp 、Native-App 这两者之间的 App,兼具「 Native App 良好用户交互体验的优势 」和「 Web App 跨平台开发的优势 」。

2. 为什么选择 Hybrid App

  1. Web 实现相对简单,一套代码,两端兼容;
  2. 产品还在快速迭代,变数大,而 Native App 开发,成本偏高;
  3. Web 开发时间较短,减少成本,可以应付产品的快速迭代;
  4. Hybrid App 的开发方式在公司其他项目上已经有了很好的运用,技术方案已有沉淀;

以上几点,是促使海外版 App 使用 Hybird 模式进行开发的主要原因。

二、整体架构

Hybird App 的开发方案的总体架构图

1. Hybird 实现方案

Hybird App 是使用 iOS 原生 、 Andoird 原生 、Web 页面 「 内置于 App 中的页面,既内嵌页 」一起实现的方式进行开发。

2. 完整的SDK工具

  1. 离线包:Web 页面资源以离线包的形式内嵌在 App 本地存储中。当访问页面的时候,WebView 对于本地存储的资源无须额外发起的网络请求,直接读取。而剩下的请求中,就只剩下 Ajax 拉取的 Json 动态数据,和渲染这部分数据时携带的图片资源,以及一些必要的埋点请求。这使 Web 页面即是在弱网的情况下也可以很快的打开;

  2. 完善的JSSDK:使用 JSSDK 与 App 进行交互,透明且跨平台地使用客户端的能力,形成交互闭环,给用户良好的交互体验;

  3. 离线包打包工具:自动化打包工具能快速的产出离线包。没有了人工干预,App 离线包正确性也能得以保证;

  4. 完善的热更新机制:App 客户端监测到离线包更新之后,客户端静默更新(用户无感知),解决了 Native App 页面不能补丁更新,只能发版修复 Bug 的问题;

3. 完善的后台系统平台

  1. 一键打包:内嵌页离线包打包工具可视化,实现一键打包产出离线包;

  2. 降级融灾:快速回退至之前版本,如有问题,快速下线新版本功能;

  3. 数据采集:完善的数据采集平台,通过数据分析优化用户体验;

  4. 灰度更新:支持根据配置进行灰度更新;

  5. 持续集成:系统平台目前还在持续集成当中,为提供更好的开发流程;

三、内嵌页的优化

我们起点海外 App 大部分页面都采用 Hybird 实现的,对于最大程度的接近 Native App 的页面性能和用户体验这两个点,我着重讲解下面两个部分:

  1. 内嵌页全局优化-接口页面并行加载;
  2. 详情页加载优化- localStorage ;

1. 内嵌页全局优化-接口页面并行加载

之前内嵌页的开发方式,是在 JS 中发出 Ajax 请求拉取数据,然后使用模版引擎拼接模版,插入到页面中,再由 WebView 进行页面渲染。

之前内嵌页的加载流程

从上图我们可以看到,虽然页面很快就有了占位显示,但是整个操作是串行的,需要等到 Ajax 数据返回之后才能看到页面。而这个从 WebView 到发起 Ajax 请求之间的时间是被浪费掉了的。

如果当 WebView 启动的时候就能发送当前页面的 Ajax 请求,我们的数据就可以提前拿到了,而这样从启动 WebView 到 Ajax 发请求的之间的空闲时间,就被我们利用上了。此时上面的流程就变成了如下的样子:

优化之后内嵌页的加载流程

当 WebView 启动的时候,App 根据 Url 地址获取相应的 Ajax 请求的地址,从而提前发出请求,等到页面本身请求发出的时候,拦截 Ajax 并判断是否是已经提前请求过的数据。如果是则基于提前请求的 Ajax 返回的数据渲染页面,如果不是则继续发送 Ajax,等到数据返回之后,再进行页面渲染。

上述做法,我们充分利用了 App WebView 的启动到 Ajax 发送获取数据之间的时间。接口请求与页面并行加载,加快了页面显示。

iOS 端书籍详情页加载对比结果

根据上组数据我们会发现页面显示的平均时间几乎快了 300ms 。在不影响页面正常加载流程的情况下,把串行操作变成并行操作,充分利用空余时间,大大缩短内嵌页白屏时间,让用户更快的看到了我们起点海外 App 的页面内容,效果显著。

2. 详情页加载优化- localStorage

采用接口与页面资源并行加载的方式,使内嵌页呈现的速度快了很多,但是由于海外用户区域广泛,接口加载时长的不确定,页面还是会有白屏的情况,接下来我们要做的就是特定页面,特殊处理。

再整个起点海外 App 页面中,详情页访问量相对较大,也是整个站点中比较重要的页面,所以其页面呈现的速度至关重要。因此本次迭代我们主要针对详情页做了特殊处理。

首先,我们先分析一下详情页的业务形态。书详情页数据相对比较稳定,并不会频繁变化,但接口数据返回需要时间,那我们是不是可以让书详情页的数据先本地存储,以求达到快速显示的效果,并同时发出 Ajax 接口,等到数据返回时再纠正页面上旧的数据。

关于本地存储,我们引入 localStorage 来进行本地存储,原因如下:

  1. localStorage 可以存储的数据容量大;
  2. localStorage 属于永久性存储;
  3. localStorage 目前移动端浏览器支持度良好;

详情页引入localStorage后的加载流程

从上图我们可以看到,当用户第一次访问书详情页时,localStorage 中没有相应书籍数据页面按正常逻辑显示,但这时我们会把这份数据缓存到 localStorage 中。当用户第二次访问同一本书的详情页时,我们根据 bookId 的 Key 值在 localStorage 中快速找到相应书详情页信息数据,并基于该缓存数据拼接模版,渲染页面。同时继续发出 Ajax 请求,待数据返回时,与 localStorage 的数据基于 Diff 算法进行对比。如果数据一致,则不做任何处理,不一致则页面基于新数据重新渲染,并且更新 localStorage 中的数据为新的 Ajax 返回数据。具体效果对比图如下,左边是未做二次加速的,右边是使用了二次加速的效果:

引入 localStorage 后的页面加载对比

详情页首屏所有数据包括书封显示时间

可以看到页面第一次展示的时候,依然能够明显看到占位图,但是当页面二次打开就直接呈现,效果很明显。

结尾~~

做了半年多的 Hybird 页面的前端开发,针对海外版 App 做了很多的优化,为的是给用户带来更好的体验。但对于 Hybird 技术自身的瓶颈,我们也无能为力。所以目前我们团队在尝试从 Hybird 到 React Native 的技术转型,以求能够在用户体验上更进一步。

同样延续上一次的分享:一个细节的优化是可以决定产品的好坏的,良好的用户体验,会吸引跟多的用户,获得更多的称赞。

以下是起点海外版的访问地址,请使劲戳戳戳~~~👇

起点海外版 App下载:
请前往 Google play / App Store [ 美区 ] 下载

起点海外版web站:
https://www.webnovel.com

起点海外版m站:
https://m.webnovel.com

更多分享,请关注YFE: