微盟关于H5页面的性能优化分析及实践转载
导语
对于开发者来说,优化性能这个词已经不绝于耳了,常道起的是首页打开要快,我要没有白屏时间,要请求次数少,把 CSS 放在页面头部先加载,JS文件/CSS文件压缩,把小图片做成雪碧图,尽量用字体图标等解决方案。我认为这些方案确实能起到优化的作用,但为什么要这样做,这些方法能优化到多少性能,如何能有效的监测到性能数据,对于一些其它性能消耗又是什么样的,这些问题都是在性能及体验优化上需要解决的事情。
正文
一、认识性能消耗在哪里
我认为要想了解性能消耗在哪里,需要先从了解访问一个链接地址直到这个链接的页面能让我们看到数据元素和进行交互的过程开始。把 PC 端或手机端的浏览器理解为客户端,把服务器理解为服务端,当一个用户从客户端输入一个页面链链接地址并进行回车的时候就是客户端向服务端进行资源请求的过程,然而,在服务端接收到客户端的请求指令并进行请求响应是服务端向客户端进行资源响应的过程,最后在请求及响应的过程中产生的时间我称为请求响应时间,性能消耗就有请求响应时间的一部分。
现如今一个网页主流是由 HTML/CSS/JS 三种类型的资源文件为主要构成,当客户端得到了服务器响应的资源后并不是可以给用户浏览的直观数据,这些资源文件的内容还需要浏览器对其内容进行解析及渲染。比如,将 HTML 的内容由 DOM 元素解析并绘制成页面文档结构,将 CSS 的内容解析并给绘制后的页面文档添妆加衣,将 JS 的内容解析及编译让页面文档变得生动可人。除了这三种类型文件的资源之外,还有其它的资源文件类型一样需要客户端去解析、编译、绘制。在客户端得到服务端响应的资源文件后进行解析、编译、绘制的时间我称为资源绘制时间,它是性能消耗里另一部分。
到这里我为了便于后面的理解,简单将性能消耗概括为请求响应时间和资源文件进行绘制时间两部分。
二、制定性能测试的维度
通过上述描述对性能消耗的组成部分有了概念之后,我认为需要对项目的性能测试制定测试维度。尝试将项目以页面为颗粒度进行拆解,得到每个页面后,我认为对每个页面进行四个维度的深入测试,我给它们定义了四个名词,它们分别是(1)首屏速度、(2)页面流畅度、(3)网络请求情况、(4)CPU/电量消耗。这四个维度的优先级顺序以每个名词前括号里的数字为依据进行顺序排序。
1、首屏速度
首屏速度的性能数据指标尤为重要,它关乎到用户的转化率、粘性等,简单理解为如果一个用户在打开页面后不能及时的得到直观数据并能进行交互的话,基本用户就要跑了。我对首屏速度采用(1)白屏时长、(2)页面加载时长、(3)首屏加载时长、(4)首次可直观数据的时长、(5)首次可交互的时长,五个指标来测量首屏速度,白屏时长是有定义为消耗为0毫秒的硬性指标。
提示:
1、上述提到页面性能消耗主要是由请求响应时间、资源绘制时间两个部分组成,然后在实际的应 用场景中,一个页面的向服务端发起的请求数量是多个及多种文件类型组成,普遍的客户端对同一 个域名的网络请求并发个数是6个,后面的请求都排在了请求队列里等待着第一梯队并发出去的6个 请求中有请求状态为完成的就进行替补排入,注意客户端只会保持并发请求数量为6个。我建议将 首屏展示所需要的资源请求放在第一梯队的网络并发中。
2、客户端并发6个请求是基于同一个域名的场景下,如果请求分布式的方式在多个域名下就可以加 大第一梯队的并发数量。例如,CDN就是基于这个方案产生的。
2、页面流畅度
解决了首屏速度后需要关注页面流畅度,我想大多数人都是不希望看到的页面是展示的断断续续的,我对页面流畅度的测试再细化为:(1)FPS直观数据、(2)响应速度、(3)内存、(4)弱网络,四个维度进行测试。
- FPS是图像领域中的定义,是指画面每秒传输帧数,通俗来讲就是指动画或视频的画面数。FPS是测量用于保存、显示动态视频的信息数量。每秒钟帧数越多,所显示的动作就会越流畅。通常,要避免动作不流畅的最低是30FPS。作为开发者的我们只要用工具关注数据指标不低于30FPS就行。
- 完成了页面流畅度和FPS直观数据后,需要再分析响应速度,这里的响应速度即包括了请求响应时间也包括了资源绘制时间,其中重点关注JavaScript的执行消耗和请求服务端接口的消耗。
- 对内存的管理要做到内存占用合理,无内存泄漏。
- 在弱网络的场景下能达到无阻塞操作,资源拉取的消耗与流量正相关。
3、网络请求情况
在分析请求响应时间的时候比较容易关注到请求响应时间占了性能消耗的绝大部分消耗,所以对网络请求情况进行了细化分析,主要分析请求是否有利用好缓存机制,有些请求是否能合并,请求的时长是否过于冗余及请求的资源大小过大并且与页面的需求不是正相关。
提示:
1、要求每个请求都是有效的,网络请求中无404请求的状态。
2、要求每个请求都是无重复的(轮询场景除外)。
4、CPU/电量消耗
在页面发生重绘、执行JS代码、Canvas动画及富媒体、发生接口请求时都会对CPU及电量生产消耗。所以需要对这些场景进行性能监控及优化去降低CPU和电量的消耗,从而使页面可以很好的兼容一些低配置机型。
三、测试工具的使用说明
上述提出分析性能从首屏速度、页面流畅度、网络请求情况、CPU/电量消耗四个维度着手并深入了细化维度,但是这些维度的数据怎么准确的得出来是下面需要说明的,我推荐使用Chrome浏览器开发工具中的Performance面板、Network面板、Rendering面板、Memory面板来测试及得到数据。
提示:
在 Chrome 浏览器中按F12打开控制台,然后就能找到 Performance 、Network、 Rendering 、 Memory 这些工具面板。
1、Performance 面板
Performance 面板的功能比较多,这里只介绍如何通过 Performance 得到JavaScript执行消耗、客户端进行渲染绘制的消耗、内存消耗数据。
3、在分析JS执行消耗时,如果发现Main中有X轴很长的块,可以选中点击这个长块并分析得出性能消耗的原因,从而可以针对性的有效优化。
提示:
点击面板中的右上角设置图标,可以选择出来Network和CPU选项,用于模拟弱网络场景下的性能数据。
2、Network 面板
1、解析面板数据.
提示:
1、页面请求的总数
2、请求资源的原始大小
3、请求资源解压后的大小
4、所有请求完成的时长
5、页面DOM请求的时长
6、触发事件的时长
提示:
1、Queued at 0:表示在当前域名下是队列的第几个请求,图例是0说明是第一个发出请求的。
2、Explanation: 表示接口一共消耗的时长。
3、Rendering 面板
4、Memory 面板
判断内存是否泄漏的先决条件是开发者要自个先定义好哪些变量是否会泄漏,然后通过Memory面板去查看这个变量是否有回收,比如A页面的a变量支持页面的数据显示,在A页面跳到B页面时,B页面的数据是用b变量支持显示,那么此时可以查看a变量是否有回收掉,如果没有那么就可能发生内存泄漏了。
最后,关于这些面板的使用方式网上已经有很多文档说明了,这里就不做过多的赘述了。
四、监控方法
看到这里是否会觉得上面的工具过于复杂和繁琐,心里是不是在想有没有一种可以简单使用并能得到直观数据的工具,当然有的啦。监控方法有两种,分别是合成监控、真实场景监控。
1、合成监控方式
合成监控是指将一个页面网址放在特定的条件下去分析性能并给出数据,但这种方式的缺点在于不能很准确的反映用户的真实场景。合成监控暂时推荐 Lighthouse 工具来分析页面性能。
1.1、使用面板
2、真实场景监控
上述提到的都是页面性能分析的一些解决方案,对于性能优化有一些重要的指标需要在用户的使用场景中收集到,例如:FCP、TTI、TTFB、TBT、LCP等。
2.1、监控指标说明
First Contentful Paint
首次内容绘制 (FCP) 指标测量页面从开始加载到页面内容的任何部分在屏幕上完成渲染的时间。对于该指标,"内容"指的是文本、图像(包括背景图像)、
在上方的加载时间轴中,FCP 发生在第二帧,因为那是首批文本和图像元素在屏幕上完成渲染的时间点。
Time to Interactive
TTI 指标测量页面从开始加载到主要子资源完成渲染,并能够快速、可靠地响应用户输入所需的时间。
工具计算TTI时间以下列步骤为依据:
a、先进行First Contentful Paint 首次内容绘制 (FCP)。
b、沿时间轴正向搜索时长至少为 5 秒的安静窗口,其中,安静窗口的定义为:没有长任务且不超过两个正在处理的网络 GET 请求。
c、沿时间轴反向搜索安静窗口之前的最后一个长任务,如果没有找到长任务,则在 FCP 步骤停止执行。
d、TTI 是安静窗口之前最后一个长任务的结束时间(如果没有找到长任务,则与 FCP 值相同)。
下图将有助于您更直观地理解上述步骤:
First to First Byte
TTFB 是衡量资源请求与响应的第一个字节开始到达之间的时间的度量。
TTFB 是以下请求阶段的总和:
- 重定向时间
- Service Worker 启动时间(在适用的场景下)
- DNS 查询
- 连接和 TLS 协商
- 请求,直到响应的第一个字节到达
减少连接建立时间和后端的延迟将有助于降低 TTFB。
Total Blocking Time
总阻塞时间 (TBT) 指标测量First Contentful Paint 首次内容绘制 (FCP)与Time to Interactive 可交互时间 (TTI)之间的总时间,这期间,主线程被阻塞的时间过长,无法作出输入响应。
每当出现(在主线程上运行超过 50 毫秒的任务)时,主线程都被视作"阻塞状态"。我们说主线程处于"阻塞状态"是因为浏览器无法中断正在进行的任务。因此,如果用户在某个长任务运行期间与页面进行交互,那么浏览器必须等到任务完成后才能作出响应。
如果任务时长足够长(例如超过 50 毫秒),那么用户很可能会注意到延迟,并认为页面缓慢或卡顿。
Largest Contentful Paint
最大内容绘制 (LCP) 指标会根据页面首次开始加载的时间点来报告可视区域内可见的最大图像或文本块完成渲染的相对时间。
Cumulative Layout Shift
CLS 测量整个页面生命周期内所发生的所有意外的布局偏移中最大一连串的布局偏移分数,每当一个可见元素的位置从一个已渲染帧变更到下一个已渲染帧时,就发生了布局偏移 。
Speed Index
速度指数衡量页面加载期间内容的视觉显示速度。
First Input Delay
FID 测量从用户第一次与页面交互(例如当他们单击链接、点按按钮或使用由 JavaScript 驱动的自定义控件)直到浏览器对交互作出响应,并实际能够开始处理事件处理程序所经过的时间。
较长的首次输入延迟通常发生在首次内容绘制 (FCP)和Time to Interactive 可交互时间 (TTI)之间,因为在此期间,页面已经渲染出部分内容,但交互性还尚不可靠。为了说明这种情况的发生缘由,我们在时间轴中加入了
FCP 和 TTI:
最后,公司也有专门开发出一个SDK工具包,用于收集这些数据,它是这个样子的。
五、结语
页面的性能消耗概括为资源请求响应时间和资源绘制时间,通过使用各种奇技淫巧的方式优化了这两部分的相关代码时,根据制定的测试维度去评判优化的效果。在开发过程中通过Chrome的性能面板及Lighthouse工具可以在合成场景下得到优化后的能效果数据。页面投入生产环境后根据开发的SDK去监控用户使用场景下的性能消耗数据并传送给后台的性能大盘上。