「这是我参与2022首次更文挑战的第1天,活动详情查看:2022首次更文挑战」。
前言
领导:"小凌,可以优化下项目的白屏时间么?",最近接到这么一个关于性能优化的任务。解决问题的第一步是要先复现问题。可是页面的白屏时间怎么计算呢?小凌首先想到的是浏览器调试工具下的Performance
。
在之前看过一个讲座,讲的是window.performance
对性能的监控。于是便对这个进行了进一步研究。
performance的作用
是浏览器暴露给js的一个接口,可以通过这个接口查看用户访问网站的连接建立时间、dns时间等信息。使用该api时需要在页面完全加载完成之后才能使用,最简单的办法是在window.onload事件中读取各种数据,因为很多值必须在页面完全加载之后才能得出。
performance.timing属性介绍
下面的图大家一定不陌生:
属性说明:
navigationStart
:浏览器处理当前网页的启动时间fetchStart
:浏览器发起http请求读取文档的毫秒时间戳。domainLookupStart
:域名查询开始时的时间戳。domainLookupEnd
:域名查询结束时的时间戳。connectStart
:http请求开始向服务器发送的时间戳。connectEnd
:浏览器与服务器连接建立(握手和认证过程结束)的毫秒时间戳。requestStart
:浏览器向服务器发出http请求时的时间戳。或者开始读取本地缓存时。responseStart
:浏览器从服务器(或读取本地缓存)收到第一个字节时的时间戳。responseEnd
:浏览器从服务器收到最后一个字节时的毫秒时间戳。domLoading
:浏览器开始解析网页DOM结构的时间。domInteractive
:网页dom树创建完成,开始加载内嵌资源的时间。domContentLoadedEventStart
:网页DOMContentLoaded事件发生时的时间戳。domContentLoadedEventEnd
:网页所有需要执行的脚本执行完成时的时间,domReady的时间。domComplete
:网页dom结构生成时的时间戳。loadEventStart
:当前网页load事件的回调函数开始执行的时间戳。loadEventEnd:当前网页load事件的回调函数结束运行时的时间戳。
计算性能指标
可以使用Navigation.timing
统计到的时间数据来计算一些页面性能指标,比如DNS查询耗时
、白屏时间
、domready
等等。如下:
- DNS查询耗时 = domainLookupEnd - domainLookupStart
- TCP链接耗时 = connectEnd - connectStartrequest
- 请求耗时 = responseEnd - responseStart
- 解析dom树耗时 = domComplete - domInteractive
- 白屏时间 = domLoading - fetchStart
- domready时间 = domContentLoadedEventEnd - fetchStart
- onload时间 = loadEventEnd - fetchStart
计算性能工具类
我们可以利用上面讲的特性来建立我们自己的性能计算工具类
:
timing.js
(function () {
function handleAddListener(type, fn) {
if (window.addEventListener) {
window.addEventListener(type, fn);
} else {
window.attachEvent('on' + type, fn);
}
}
function getTiming() {
try {
var time = performance.timing;
var timingObj = {};
var loadTime = (time.loadEventEnd - time.loadEventStart) / 1000;
if (loadTime < 0) {
setTimeout(function () {
getTiming();
}, 200);
return;
}
timingObj['重定向时间'] = (time.redirectEnd - time.redirectStart) / 1000;
timingObj['DNS解析时间'] = (time.domainLookupEnd - time.domainLookupStart) / 1000;
timingObj['TCP完成握手时间'] = (time.connectEnd - time.connectStart) / 1000;
timingObj['HTTP请求响应完成时间'] = (time.responseEnd - time.requestStart) / 1000;
timingObj['DOM开始加载前所花费时间'] = (time.responseEnd - time.navigationStart) / 1000;
timingObj['DOM加载完成时间'] = (time.domComplete - time.domLoading) / 1000;
timingObj['DOM结构解析完成时间'] = (time.domInteractive - time.domLoading) / 1000;
timingObj['脚本加载时间'] = (time.domContentLoadedEventEnd - time.domContentLoadedEventStart) / 1000;
timingObj['onload事件时间'] = (time.loadEventEnd - time.loadEventStart) / 1000;
timingObj['**白屏时间**'] = (time.domLoading - time.fetchStart) / 1000;
timingObj['页面完全加载时间'] = timingObj['重定向时间'] + timingObj['DNS解析时间'] + timingObj['TCP完成握手时间'] + timingObj['HTTP请求响应完成时间'] + timingObj['DOM结构解析完成时间'] + timingObj['DOM加载完成时间'];
Object.keys(timingObj).forEach((key) => {
console.log(key + ':' + timingObj[key] + '毫秒(ms)');
});
console.log(performance.timing);
} catch (e) {
console.log(e);
console.log(timingObj);
console.log(performance.timing);
}
}
handleAddListener('load', getTiming);
})();
复制代码
index.html
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<link rel="icon" href="<%= BASE_URL %>favicon.ico" />
<title>小凌爱前端</title>
</head>
<body>
<div id="app"></div>
<!--性能监测js-->
<script type="text/javascript" charset="utf-8" src="timing.js"></script>
</body>
</html>
复制代码
如此我们便可以在首页种监听我们的性能变化了。
浏览器兼容性
目前关于Window.performance.timing
的浏览器兼容性如下图所示: