首页 > 作文

让老板虎躯一震的前端技术,KPI杀手

更新时间:2023-04-03 13:11:30 阅读: 评论:0

本文由云+社区发表

天下武功,唯 (wei) 快(fu) 不(bu) 破(po)。

随着近几年的前端技术的高速发展,越来越多的团队使用 react、vue 等 spa 框架作为其主要的技术栈。以 react 应用为例,从性能角度,其最重要的指标可能就是首屏渲染所花费的时间了。那么今天,我们要给大家分享的一个把优化做到极致的故事。

我们的目标是让 h5 的页面也能够拥有 native 般的体验,如果你还在寻求什么技术能够让老板虎躯一震(拯救你的kpi),那么这篇文章或许能够帮助到你。

企鹅辅导课程详情页是什么

企鹅辅导详情页

课程详情页是腾讯旗下企鹅辅导 app 中最重要页面之一,也是流量最大的页面之一,所以它的打开速度也是至关重要的。

这是一个使用 react 编写的 h5 页面,运行于多端,包括: 企鹅辅导app手机 qq手机浏览器

架构演变

纯异步渲染

我们知道当前主流的 spa 的应用的默认渲染方式都是这样的:

在这种情况走遍天下书为侣小练笔下,从加载页面到用户看到页面(首屏渲染所花费的时间)就是上图中灰色边框区域所包括的时间。

这是最慢的一种方式,就算 cgi 够快,最少要花费 1s2s 左右的时间了。

接着我们简单优化一下:

把静态资源缓存起来,这样下次用户打开的时候就不用从网络请求了。第 步拉取 cgi 这个动作是否可以提前呢?我们可以在请求 html 之后,先通过一段 js 脚本去请求 cgi 数据,后面第 步的时候,就可以直接拿到数据了,这就是 cgi 预加载

怎么做到呢?我们的方案是统一封装 request 请求工具,在用 webp考研的时间ack 打包的时候,会往页面顶部注入一段 预加载 cgi 的 js 代码,维护一个cgi 与 data 对应 map,后面发请求的时候,先去 map 里取值,如果有值的话直接拿出来,没有的话则发起http 请求。(具体请查阅我们团队开源的 preload 工具)

这种模式还有一些其他的优化的方法:

在 html 内实现 loading 态或者骨架屏;去掉外联 css;使用动态 polyfill;使用 splitchunksplugin 拆分公共代码;正确地使用 webpack 4.0 的 tree shaking;使用动态 import,切分页面代码,减小首屏 js 体积;编译到 es2015+,提高代码运行效率,减小体积;使用 lazyload 和 placeholder 提升加载体验。

效果如下图所示:

异步渲染

直出同构

在异步的模式下,除了上述优化,我们还在端内(企鹅辅导 app、手机 qq)内做了离线包缓存(腾讯手q方面独立研发出来的针对手机端优化的方案,简而言之就是将静态资源缓存在手机 app 内),经过我们的数据测试,首屏渲染大概能够达到秒开(1s左右) 的效果。

-w300

但对有着性能极致追求的我们来说,肯定是不会满意的。

继续优化,最容易、最大众的套路肯定就是直出(服务端渲染)了。

现在直出的方案已经有很多很多种,这里也不多做介绍了,如果您想了解更多关于服务端渲染的方案,请参考这篇文章。

直出针对首屏时间的优化效果是非常明显的,经过我们的测试,数据大概能够提升25%左右。

直出之后的效果如下图:

直出同构

可以看到对于首屏来说,没有了【加载中…】的等待时间,视觉体验提升了不少。

pwa 直出

pwa

针对上述、常见的直出应用来说,我们能够优化的点在哪里呢?让我们来详细分析一波,这也是今天我们要给大家分享的重点。

首先看看直出应用各个环节的耗时表 (本地环境 2018款 imac):

过程名称过程花费node 内 cgi 拉取300 msrenderto亡羊补牢string20 ms网络耗时10 ms前端html渲染30 ms

从上面的英语作文结尾表中我们看出,直出渲染的耗时的大头还是在 cgi 接口的拉取上。

我们现在提出两个问题

cgi 接口的数据是否可以缓存 ?html 又是否可以缓存 ?
一、接口的动静分离

动态信息

这个页面的接口数据中,有一些数据,是实时变动的, 比如:当前还剩多少个名额、此时此刻课程的价格、用户是否购买过这个课程等。

这些数据的特性决定了这个数据接口不能够被缓存。(假设将其缓存,那么就会存在可能用户进来看到当前还剩下10个名额,其实课程已经卖光了的情况)

为了这个时间耗时的大头,我们做了cgi接口的动静分离

将与用户态、当前时间没有关联的数据(比如课程标题课程上课的时间试听模块的地址等)放在一个接口(静态接口),其他变化的数据放在另一个接口(动态接口)。

那么可以使用静态的接口来做服务端渲染,好处是第一比较快(少了动态的信息,而且后台也可以做缓存),第二 node 直出可以做缓存了。

二、直出 redis 缓存

这样我们就可以将那部分静态的、不会经常变动的数据用来直出 html,然后将这个 html 文件缓存到 redis 中

客户端请求此网页,node 端接受到请求之后,先去 redis 里拿缓存的 html,如果 redis 缓存没有命中,则拉取静态的 cgi 接口渲染出 html存入 redis。

客户端拿到 html 之后,会立刻渲染,然后再用 js 去请求动态的数据,渲染到相应的地方。

做完之后我们可以看到优化效果的提升是非常非常明显的:

直接从 262ms 提升到了 16ms !(本地环境),简直飞一般的感觉,妈妈再也不用担心领导看耗时了。

三、pwa 直出缓存

关于什么是 pwa ,以及如何使用,请移步这篇文章。

做了 node 端直出的 html 缓存之后,我们接着优化,接着思考,是否可以在客户端也缓存 html,这样连网络延时这部分消耗也省掉呢。

答案就是使用 pwa 在客户端做离线缓存,将我们直出的 html 缓存在客户端,每次用户请求的时候,直接从 pwa 离线缓存里取出对应的直出页面(html)响应给用户,响应之后紧接着请求 node 服务更新本地的 pwa 缓存。(如下图所示)

核心代码:

lf.addeventlistener("fetch", event => {   // todo other logic (maybe fetch filter)  // core logic  event.respondwith(    caches.open(cachename).then(function(cache) {      return cache.match(cachecoururl).then(function(respon) {        var fetchpromi = fetch(cachecoururl).then(function(          networkrespon        ) {          if (networkrespon.status === 200) {            cache.put(cachecoururl, networkrespon.clone());          }          return networkrespon;        });        return respon || fetchpromi;      });    })  );});

废话不多说,先看效果对比 (左 pwa 直出;右 离线包):

duibi

从上图可以看出,使用了 pwa 直出缓存之后,首屏渲染基本是毫秒开,可以说与 native 并肩了。

经过我们的数据测试,使用 pwa 直出缓存,首屏渲染的时间最好可以到400ms左右级别:

pwa 直出细节优化

一、防页面跳动

因为对接口进行了动静分离,使用静态接口直出页面,然后在客户端拉取动态数据渲染完。这就可能会导致页面的抖动(比如详情页中的试听模块,是在客户端渲染的)。

因为高度改变了,视觉上就会出现抖动(具体可以参考上面章节直出时候的 gif 截图)。

要去掉页面抖动的情况,就必须保证容器的高度在直出时候已经存在了

比如这个试听模块,其实这个封面图和试听按钮是可以在服务端渲染出来的,而后面的 video 模块则必须要在客户度渲染(腾讯云 tcplayer)。

所以这里可以拆分成:(试听封面 + 按钮 + 时间)服务端渲染 + 底层 video(客户端渲染)。

有些需要在客户端计算高度的容器(表现为常放在 componentdidmount 里计算),如果它们依赖客户端环境(比如依赖当前系统是安卓还是 ios),就导致他们肯定不能放在服务端直接渲染出来,这又怎么办呢?

这里我们的做法,是将这些计算放在 html body 之前,通过内联的脚本嵌入,计算出当前环境,给 body 加上一个特定的类(class),然后在这个特定的类下面的元素,就可以通过 css 给予特定的样式。比如下面代码:

/* * 因为在不同的手机 app 环境内,页面的 padding 是不一样的。 * 我们要在页面渲染完之前加上相应的 padding  */var regexp_fudao_app = /educationapp/;if (  typeof navigator !== "undefined" &&  regexp_fudao_app.test(navigator.uragent)) {  if (/android/i.test(navigator.uragent)) {    document.body.classlist.add("androidfudaoapp");  } el if (/iphone|ipad|ipod|ios/i.test(navigator.uragent)) {    if (window.screen.width === 375 && window.screen.height === 812) {      document.body.classlist.add("iphonexfudaoapp");    } el {      document.body.classlist.add("iosfudaoapp");    }  }}.androidfudaoapp .tt {  padding-top: 48px;  background-position-y: 84px;}.iphonexfudaoapp .tt {  padding-top: 88px;  backggood副词形式round-position-y: 124px;}.iosfudaoapp .tt {  padding-top: 64px;  background-position-y: 100px;}

然后把这段代码通过构建插入到页面 body 之前。

-w500

防抖动优化效果如下 (左优化完,右未优化):

duibi_doudong

二、冷启动预加载

虽然我们做了 pwa 离线缓存,但是对于冷启动来说,客户端里面的 pwa 缓存还是没有的,这样就会导致初次点击页面,渲染速度相对慢一点。

这里我们可以在 app 启动的时候,用一个预加载的脚本最大限度的拉取用户可能访问的页面。

核心代码如下:

// 预加载页面时, pwa 预缓存课程详情页面的直出function prefetchcache(fetchurl) {    fetch("https://you prefetch cgi")      .then(data => {        return data.json();      })      .then(res => {        const { courinfo = [] } = res.result || {};        courinfo.foreach(item => {          if (item.cid) {            caches.open(cachename).then(function(cache) {              fetch(`${coururl}?cour_id=${item.cid}`).then(function(                networkrespon              ) {                if (networkrespon.status === 200) {                  cache.put(                    `${coururl}?cour_id=${item.cid}`,                    networkrespon.clone()                  );                }                // return networkrespon;              });            });          }        });      })      .catch(err => {        // to monitor err      });}

pwa 直出遗留问题

一、兼容性问题

随着 pwa 技术的发展,现今大部分手机以及 pc 环境已经支持对 pwa 进行了支持。经过我们的测试发现:安卓基本上都是支持的,ios 需要11.3以上才支持。

rvice workers 兼容性图

二、ios 渲染问题

很多的经验告诉我们,外联的 script 标签要放在 body 的后面,因为它会阻塞页面的 dom 渲染。

经过测试发现,ios 的 webview (uiwebview)渲染机制并不会上述一样,而是要等到后面的 js 执行完之后才渲染页面,如果是这样,我们的直出渲染优化就没有效果了(因为 html 并不在最开始渲染),这里可以使用 script 标签的 asyncdefer 属性来达到异步渲染的作用。

升级 wkwebview 之后,情况得到改善,渲染正常。

附录

参考资料
pwa 的探索与最佳实践react 16 加载性能优化指南

此文已由作者授权腾讯云+社区在各渠道发布

获取更多新鲜技术干货,可以关注我们

本文发布于:2023-04-03 13:11:21,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/zuowen/71c3e9f5f159590cec64350896fe50d1.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

本文word下载地址:让老板虎躯一震的前端技术,KPI杀手.doc

本文 PDF 下载地址:让老板虎躯一震的前端技术,KPI杀手.pdf

标签:缓存   页面   接口   数据
相关文章
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图