前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Webview秒开探索:让你的H5“快人一步”

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

原创
作者头像
南山种子外卖跑手
发布2022-03-07 10:47:22
1.9K0
发布2022-03-07 10:47:22
举报
文章被收录于专栏:南山种子外卖跑手的专栏
Webview秒开探索:让你的H5“快人一步”.png
Webview秒开探索:让你的H5“快人一步”.png

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

背景

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

业务场景

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

image.png
image.png

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

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

  • 实时更新,与后台管理系统操作同步(后台新增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,把最终带有数据的页面返回给前端,流程图如下:

image.png
image.png

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

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

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

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

image.png
image.png

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

  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成功率也相对比较高,可以采取。

改后的流程如下:

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

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

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

技术栈:nodejs、react、redis、ReactDOMServer

整理后的流程如下:

image.png
image.png

redis具备高性能的特点,参考资料《redis高性能原理》 ReactDOMServer可以参考官方描述,主要作用是在服务端将react函数实例化成一个dom

Ajax vs Redis 效率

Ajax

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

image.png
image.png

Redis

使用nodejs+redis ssr处理耗时:

代码语言:shell
复制
{"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文档流开销:

image.png
image.png

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

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

效果展示

ssr秒开方案

111.gif
111.gif

普通异步加载

222.gif
222.gif

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景
  • 业务场景
  • 秒开的技术探讨
    • 网页请求流程
      • part1:浏览器发起document请求
      • part2:document到页面渲染
      • 方案对比
      • Ajax
      • Redis
  • Ajax vs Redis 效率
  • 效果展示
    • ssr秒开方案
      • 普通异步加载
      相关产品与服务
      云数据库 Redis®
      腾讯云数据库 Redis®(TencentDB for Redis®)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档