Webview秒开探索:让你的H5“快人一步”

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 Tair(兼容Redis),内存型 2GB
全局流量管理 GTM,标准版 1个月
简介: 作为前端技术的重要衡量指标之一,首屏渲染效率无疑前端老生常谈的话题了。这篇文章就来聊下如何在常见的H5环境下,做到页面秒开。

网络异常,图片无法展示
|

本文为原创文章,引用请注明出处,欢迎大家收藏和分享💐💐

背景

如今的前端技术层出不穷,无论是reactvue等框架还是跨端解决方案,为使用场景和开发效率做了不少的提升,但作为前端技术的重要衡量指标之一,首屏渲染效率无疑前端老生常谈的话题了。这篇文章就来聊下如何在常见的H5环境下,做到页面秒开。

业务场景

这里也是引用笔者之前做过的一个业务来举例:有一个模拟用户朋友圈记录的H5页面,用户能通过管理端来编辑一条朋友圈消息「图文|视频」,并展示在这个H5页面上。如下图:

网络异常,图片无法展示
|

在这个场景下,如何快速打开页面并把朋友圈动态展示出来就显得尤为重要了,因为首屏速度越快,有效曝光率就越高、挽留率也就越高,如何提高页面的访问速度可以说是这个业务的硬性指标

另外,这个业务还有另外的技术要求:

  • 实时更新,与后台管理系统操作同步(后台新增1条消息前端就要有新记录);
  • 秒开,最好能达到native页面的体验感。

秒开的技术探讨

网页请求流程

在确定方案前,我们先回顾下网页的请求全流程:

part1:浏览器发起document请求

  1. app cache:检查域名缓存,如果有缓存就不需要DNS解析域名;
  2. DNS解析:把域名解析成IP;
  3. TCP连接:浏览器发起TCP连接请求。经过标准的TCP握手流程,建立TCP连接;
  4. HTTP请求:按照HTTP协议标准发送一个索要网页的请求;
  5. API网关转发:一般服务配备业务转发能力,根据不同路径转发到不同服务;
  6. 负载均衡:计算负载,转发到一台后端的真实Web服务器,Web服务器收到请求,产生响应,并将网页返回。

part2:document到页面渲染

  1. 根据 HTML 结构生成 DOM Tree
  2. 根据 CSS 生成 CSSOM
  3. 将 DOM 和 CSSOM 整合形成 RenderTree
  4. 根据 RenderTree 开始渲染和展示;
  5. 遇到script标签时,会执行并阻塞渲染,因为 Javascript 代码有权利改变DOM树;
  6. 异步请求触发,完善页面数据,最终得到一个最终页面。

由此看来,对于首屏的常规优化,我们可以采取资源压缩&合并、cdn加速、骨架图等一系列措施,这都是老生常谈的优化方案了;

其实,对于动态页面,往往需要在onload后发起额外的异步请求(上述第6步),在这个过程中,会有或多或少的等待时间,降低用户体验。


思考:有没有办法让这类页面提前渲染出最终形态??

没错,我们可以采用ssr渲染方案(即是在part1过程进行数据提前处理),在请求html的时候在网关层进行拦截,转发到后台服务把数据写入html,把最终带有数据的页面返回给前端,流程图如下:

网络异常,图片无法展示
|

这是常规的SSR渲染方案,只是异步数据拉取时机由前端调用改为服务端调用。按理说,这时候的:首屏时长=服务请求时长+服务获取异步数据时长+浏览器渲染页面时长

虽然说服务器拉数据比前端更稳定和快速,但带来了额外的问题:

  • 拉取数据服务宕机,导致html请求阻塞,前端页面一直处于空白等待状态,需要服务端做额外逻辑兼容;
  • 拉取数据耗时较长时,前端页面的白屏时间也相应增加,不但没有实现秒开效果,反而拖慢页面加载速度;


思考plus:有没有办法在实现SSR情况下又能保证页面秒开?

网络异常,图片无法展示
|

这样,我们再想想在哪个流程点可以优化下:

  1. 放弃ssr,从优化前端资源入手
  2. ssr+本地存储
  3. 设置ssr数据拉取接口超时,前端页面onload后加上ajax请求补偿
  4. node服务+redis数据存储,代替额外的数据请求

方案对比

放弃ssr,从优化前端资源入手

  • 在 HTML 内实现 Loading 态或者骨架屏;
  • 去掉外联 css;
  • 使用动态 polyfill;
  • 使用 SplitChunksPlugin 拆分公共代码;
  • 正确地使用 Webpack 4.0 的 Tree Shaking;
  • 使用动态 import,切分页面代码,减小首屏 JS 体积;
  • 编译到 ES2015+,提高代码运行效率,减小体积;
  • ...

缺点:无法抹平异步数据加载带来的页面抖动,但可以快速给用户呈现页面雏形,综合考虑无法满足需求,舍弃。

ssr+前端本地存储

使用localstorage对首次请求得到的数据缓存,并设置有效时间,在有效期内直接读取本地数据...

缺点:无法保证数据实时性,无法满足需求,舍弃。

设置ssr数据拉取api超时,前端页面onload后加上ajax请求补偿

这个就是在服务器拉取数据时加上短暂的时间判断,在接口超时情况下直接返回没有ssr渲染的页面,前端在首屏完成后再异步请求数据。

分析:服务器之间的请求相对比较稳定而高效,ssr成功率也相对比较高,可以采取。

改后的流程如下:

网络异常,图片无法展示
|

node服务+redis数据存储,代替额外的数据请求「推荐」

这方案大致思路:admin在管理后台新增朋友圈记录时,顺便拉取该用户最近20条记录,并把它们写进redis中。之后在H5请求数据时,先进redis检查是否有用户记录,有就直接写ssr并返回document,达到极速渲染效果。

一般对于数据量不是很大的请求,http在跨服务上的请求平均耗时100+ms起,而redis能达到10+ms的级别,在这2种方式,效率差别尤为明显。

技术栈:nodejs、react、redis、ReactDOMServer

整理后的流程如下:

网络异常,图片无法展示
|

redis具备高性能的特点,参考资料《redis高性能原理》

ReactDOMServer可以参考官方描述,主要作用是在服务端将react函数实例化成一个dom

Ajax vs Redis 效率

Ajax

对于异步获取数据的http请求开销:

网络异常,图片无法展示
|

Redis

使用nodejs+redis ssr处理耗时:

{"msg":"开始处理demo_user的ssr渲染...","time":"2021-04-11T03:36:45.842Z","v":0}
{"msg":"redis数据读取成功,共20条数据","time":"2021-04-11T03:36:45.858Z","v":0}
{"msg":"ssr渲染处理成功","time":"2021-04-11T03:36:45.869Z","v":0}

浏览器视角,获取html文档流开销:

网络异常,图片无法展示
|

整个数据获取+处理过程大约只需要27ms,而首屏完全加载时间也保证在329ms,对比起来,我们在请求html文档时,在服务器直接对redis读取数据并写入ssr,效率提高了不止一个档次。

那如何保证redis数据是最新的?其实也很简单,在对用户数据进行数据库操作同时,更新一份到redis就可以了,而且ssr用于首屏渲染只需要前20条数据,固redis保存的数据量是可控的。当然,redis也不是绝对可靠的,所以我们还需要做些补偿方案,例如在redis获取数据失败时,改调用接口获取数据等。

效果展示

ssr秒开方案

网络异常,图片无法展示
|

普通异步加载

网络异常,图片无法展示
|

写在最后

欢迎大家关注本人公众号「是马非马」,一起玩耍起来!🌹🌹

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore     ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
移动开发 小程序 Android开发
小程序webview组件嵌H5页面,安卓手机没有问题,苹果有部分页面不显示
小程序webview组件嵌H5页面,安卓手机没有问题,苹果有部分页面不显示
184 0
|
4月前
|
存储 移动开发 Android开发
使用kotlin Jetpack Compose框架开发安卓app, webview中h5如何访问手机存储上传文件
在Kotlin和Jetpack Compose中,集成WebView以支持HTML5页面访问手机存储及上传音频文件涉及关键步骤:1) 添加`READ_EXTERNAL_STORAGE`和`WRITE_EXTERNAL_STORAGE`权限,考虑Android 11的分区存储;2) 配置WebView允许JavaScript和文件访问,启用`javaScriptEnabled`、`allowFileAccess`等设置;3) HTML5页面使用`<input type="file">`让用户选择文件,利用File API;
|
6月前
|
Web App开发 数据采集 移动开发
开发uniapp过程中对app、微信小程序与h5的webview调试
开发uniapp过程中对app、微信小程序与h5的webview调试
1073 1
|
Web App开发 移动开发 JavaScript
通过H5(浏览器/WebView/其他)唤起本地app
通过H5(浏览器/WebView/其他)唤起本地app
|
移动开发 小程序 Android开发
uniapp使用webview将页面转换成图片支持h5、app、小程序
uniapp使用webview将页面转换成图片支持h5、app、小程序
|
移动开发 小程序 Android开发
小程序webview组件,小程序和webview交互,小程序内联h5页面,小程序webview内网页实现微信支付
小程序webview组件,小程序和webview交互,小程序内联h5页面,小程序webview内网页实现微信支付
273 0
|
移动开发 API Android开发
一行代码搞定react-native-webview 安卓无法播放h5视频问题
一行代码搞定react-native-webview 安卓无法播放h5视频问题
565 0
一行代码搞定react-native-webview 安卓无法播放h5视频问题
|
移动开发 JavaScript Android开发
webview 优化加载 H5 应用(尝试方案)
webview 优化加载 H5 应用(尝试方案)
374 0
|
Android开发
app内嵌WebView调用H5支付/授权点击按钮无反应之解决方案
说明       针对目前商户反馈如下问题 1、app内嵌WebView,用户手机安装了支付宝客户端支付流程没有问题,没有安装支付宝客户端,部分机型调起支付宝h5页面支付,在输入完账号和密码后,点击&quot;下一步&quot;没有反应。
2396 0
|
Web App开发 移动开发 JavaScript
Android与H5混合开发「kotlin,WebView」
Android与H5的交互「kotlin,WebView」 文章参考自尚硅谷-Android与H5的互调,由衷感谢。语言是使用了kotlin,如果不熟悉kotlin,建议看看这篇文章,kotlin还是很值得学习的。
2249 0