编辑
2023-02-11
前端
0
请注意,本文编写于 650 天前,最后修改于 116 天前,其中某些信息可能已经过时。

目录

前言
Performance
实战测试
一、 domContentLoadedEventStart 和 domContentLoadedEventEnd 区别
二、DOMContentLoaded 是对应domContentLoadedEventStart 和 domContentLoadedEventEnd 哪个字段。
三、 当前网页load事件还没有发生,返回0。
性能指标的计算
一、白屏时间
1、开始渲染时间
2、头部资源加载时间
二、首屏时间
三、用户可操作时间
四、页面总下载时间
五、常见的指标
性能工具

前言

前端性能关系到页面的用户体验,页面的用户体验影响了产品的留存率,而产品则直接决定了一个公司的生死存亡。

Global Web Performance Matters for ecommerce的报告中指出:

  • 57%的用户更在乎网页在3秒内是否完成加载。

  • 52%的在线用户认为网页打开速度影响到他们对网站的忠实度。

  • 每慢1秒造成页面 PV 降低11%,用户满意度也随之降低降低16%。

  • 近半数移动用户因为在10秒内仍未打开页面从而放弃。

在我们做前端性能优化的时候,我们必须知道我们所做的优化到底能提升多少性能,这时候就有必要对前端性能进行监控。当然,我们现在这边讨论的前端性能,是关于页面加载和延迟方面的性能,暂时不讨论对错误处理的相关内容。

Performance

首先简单介绍一下前端相关的性能指标,我们关注的几个指标如下。

  • 白屏时间 = 地址栏输入URL回车 - 浏览器出现第一个元素
  • 首屏时间 = 地址栏输入URL回车 - 浏览器第一屏渲染完成
  • 用户可操作时间
  • 页面总下载时间

对开发人员而言,我们常用的性能指标API就是Performance。Performance 接口可以获取到当前页面与性能相关的信息。

我们使用window.performance就可以获得 performance对象。

在控制台我们打印performance,可以看到performance对象包含五个属性。

  • navigation 提供了在指定的时间段里发生的操作相关信息,包括页面是加载还是刷新、发生了多少次重定向等等。

  • timing 对象包含延迟相关的性能信息,也是这次我们需要

  • memory 对象

    • jsHeapSizeLimit: 内存大小限制
    • totalJSHeapSize: 可使用的内存
    • usedJSHeapSize: JS 对象占用的内存
  • timeOrigin 返回性能测量开始时的时间的高精度时间戳

我这边先给出上述字段的含义,个人认为比较重要的节点加粗了

  • navigationStart: 表示从上一个文档卸载结束时的 unix 时间戳,如果没有上一个文档,这个值将和 fetchStart 相等
  • unloadEventStart: 表示前一个网页(与当前页面同域)unload 的时间戳,如果无前一个网页 unload 或者前一个网页与当前页面不同域,则值为 0。
  • unloadEventEnd: 返回前一个页面 unload 时间绑定的回掉函数执行完毕的时间戳。
  • redirectStart: 第一个 HTTP 重定向发生时的时间。有跳转且是同域名内的重定向才算,否则值为 0。
  • redirectEnd: 最后一个 HTTP 重定向完成时的时间。有跳转且是同域名内部的重定向才算,否则值为 0。
  • fetchStart: 浏览器准备好使用 HTTP 请求抓取文档的时间,这发生在检查本地缓存之前
  • domainLookupStart/domainLookupEnd: DNS 域名查询开始/结束的时间,如果使用了本地缓存(即无 DNS 查询)或持久连接,则与 fetchStart 值相等
  • connectStart: HTTP(TCP)开始/重新 建立连接的时间,如果是持久连接,则与 fetchStart 值相等。
  • connectEnd: HTTP(TCP) 完成建立连接的时间(完成握手),如果是持久连接,则与 fetchStart 值相等。
  • secureConnectionStart: HTTPS 连接开始的时间,如果不是安全连接,则值为 0。
  • requestStart: HTTP 请求读取真实文档开始的时间(完成建立连接),包括从本地读取缓存。
  • responseStart: HTTP 开始接收响应的时间(获取到第一个字节),包括从本地读取缓存
  • responseEnd: HTTP 响应全部接收完成的时间(获取到最后一个字节),包括从本地读取缓存
  • domLoading: 开始解析渲染 DOM 树的时间,此时 Document.readyState 变为 loading,并将抛出 readystatechange 相关事件。
  • domInteractive: 完成解析 DOM 树的时间,Document.readyState 变为 interactive,并将抛出 readystatechange 相关事件,注意只是 DOM 树解析完成,这时候并没有开始加载网页内的资源。
  • domContentLoadedEventStart: DOM 解析完成后,网页内资源加载开始的时间,在 DOMContentLoaded 事件抛出前发生。
  • domContentLoadedEventEnd: DOM 解析完成后,网页内资源加载完成的时间(如 JS 脚本加载执行完毕)。
  • domComplete: DOM 树解析完成,且资源也准备就绪的时间,Document.readyState 变为 complete,并将抛出 readystatechange 相关事件。
  • loadEventStart: load 事件发送给文档,也即 load 回调函数开始执行的时间。
  • loadEventEnd: load 事件的回调函数执行完毕的时间。

(1) DOMContentLoaded 是指页面元素加载完毕,但是一些资源比如图片还无法看到,但是这个时候页面是可以正常交互的,比如滚动,输入字符等。 jQuery 中经常使用的 $(document).ready() 其实监听的就是 DOMContentLoaded 事件。

(2) load 是指页面上所有的资源(图片,音频,视频等)加载完成。jQuery 中 $(document).load() 监听的是 load 事件。

实战测试

由于上面的一些字段解释源于网上的文档和资料,所以我自己需要做一些代码上的测试。

一、 domContentLoadedEventStartdomContentLoadedEventEnd 区别

代码如下,我们计算了DOMContentLoaded的回调执行时间。

javascript
window.addEventListener('DOMContentLoaded', () => { console.time('DOMContentLoaded') for (let i=0;i<1000000000;i++){ } console.timeEnd('DOMContentLoaded') })

在浏览器控制台,我们打印了这两个字段的差值,发现两个字段的差值刚好等于DOMContentLoaded的回调执行时间,网上关于字段的解释正确。并且,真正触发DOMContentLoaded事件应该是domContentLoadedEventStart对应的时间。

二、DOMContentLoaded 是对应domContentLoadedEventStartdomContentLoadedEventEnd 哪个字段。

在浏览器控制台,我们打印了它和navigationStart的差值。

在浏览器network的下面,我们看到显示的DOMContentLoaded时间是1.34秒

结论:浏览器上的DOMContentLoaded的时间实际代表的是domContentLoadedEventEnd 的时间。

三、 当前网页load事件还没有发生,返回0。

DOMContentLoaded事件的回调里,我们发现loadEventStartloadEventEnd都是0。在load事件的回调里,我们发现loadEventStart有值,loadEventEnd是0。

结论:如果需要计算load的时间的话,一定要注意代码在页面load事件触发以后再去计算。

性能指标的计算

一、白屏时间

再明确一下白屏时间的定义,用户从打开页面开始到页面开始有东西呈现为止。

如果是chrome高版本,直接可以通过下面代码获得

// 白屏时间 (chrome.loadTimes().firstPaintTime - chrome.loadTimes().startLoadTime)*1000;

如果是没有该API的普通浏览器

我们通常认为浏览器开始渲染 <body> 或者解析完 <head> 的时间是白屏结束的时间点。

所以,白屏时间 = 开始渲染时间 + 头部资源加载时间

1、开始渲染时间
javascript
//开始渲染时间 startTime = performance.timing.domLoading - performance.timing.navigationStart;
2、头部资源加载时间

我们在<head>的前面计时开始,在<head>最末尾计时结束,中间的差值就是头部资源加载时间。

html
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width,initial-scale=1"> <script> var start_time = new Date; //测试时间起点,实际统计起点为 DNS 查询 </script> <script> for(let i=0; i<10000000000; i++){ } </script> <!-- 页面 CSS 资源 --> <link rel="stylesheet" href="xx.css"> <script> var end_time = +new Date; //时间终点 var headTime = end_time - start_time; //头部资源加载时间 </script> </head> <body> </body> </html>

所以最终,白屏时间 = 开始渲染时间(startTime) + 头部资源加载时间(headTime)

二、首屏时间

再明确一下首屏时间的定义,用户浏览器首屏内所有内容都呈现出来所花费的时间。

影响首屏的主要因素是图片的加载。基本流程如下

html
首屏位置调用 API 开始统计 -> 绑定首屏内所有图片的 load 事件 -> 页面加载完后判断图片是否在首屏内,找出加载最慢的一张 -> 首屏时间

对于网页高度小于屏幕的网站来说,只要在页面底部加上脚本打印当前时间即可;或者对于网页高度大于一屏的网页来说,只要在估算接近于一屏幕的元素的位置后,打印一下当前时间。当然这个时间要得把首屏中所有图片的加载时间也算上。

三、用户可操作时间

用户可操作时间影响交互体验,通常我们把所有事件的绑定都放在domReady以后,所以用户可操作的时间可以等于DOM解析完毕的时间。

javascript
用户可操作时间 = performance.timing.domInteractive - performance.timing.navigationStart

四、页面总下载时间

页面总下载时间可以统计onload时间,load事件必须等到页面内包括图片的所有元素加载完毕后才能触发。

javascript
页面总下载时间 = performance.timing.loadEventEnd - performance.timing.navigationStart

五、常见的指标

javascript
// 计算加载时间 function getPerformanceTiming() { var t = performance.timing var times = {} // 页面加载完成的时间,用户等待页面可用的时间 times.loadPage = t.loadEventEnd - t.navigationStart // 解析 DOM 树结构的时间 times.domReady = t.domComplete - t.responseEnd // 重定向的时间 times.redirect = t.redirectEnd - t.redirectStart // DNS 查询时间 times.lookupDomain = t.domainLookupEnd - t.domainLookupStart // 读取页面第一个字节的时间 times.ttfb = t.responseStart - t.navigationStart // 资源请求加载完成的时间 times.request = t.responseEnd - t.requestStart // 执行 onload 回调函数的时间 times.loadEvent = t.loadEventEnd - t.loadEventStart // DNS 缓存时间 times.appcache = t.domainLookupStart - t.fetchStart // 卸载页面的时间 times.unloadEvent = t.unloadEventEnd - t.unloadEventStart // TCP 建立连接完成握手的时间 times.connect = t.connectEnd - t.connectStart return times }

性能工具

页面性能的评估与监控有很多工具,下面简单介绍几个常用的工具:

  • Page Speed: 谷歌开发的分析和优化网页的工具,可以作为浏览器插件使用  

  • WebPageTest:一款非常优秀的网页前端性能测试工具。使用 WebPagetest,你可以详细掌握网站加载过程中的瀑布流、性能得分、元素分布、视图分析等数据。其中比较直观的视图分析功能可以直接看到页面加载各个阶段的截屏。国内也有利用 WebPagetest 搭建的性能测试平台,推荐使用阿里测。 

  • PhantomJS:自动化监测,模拟Phantom JS 是一个服务器端的 JavaScript API 的 WebKit,基于它可以轻松实现 web 自动化测试。类似的有berserkJS。但是都是服务器模拟测试,不能监控用户真实环境。

本文作者:sora

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!