前端速度统计(性能统计)
Opened this issue · 0 comments
#1、网站都有哪些指标?
1.1 首屏时间
这个指标对于大多数网站来说,非常重要。那么何为首屏时间呢?引用百度百科里的一句话,就是:
网站用户体验的一个重要指标。 指一个网站被浏览器如IE窗口上部800*600的区域被充满所需时间。
其实就是你的网页刚进入时,渲染完整个浏览器屏幕的时间。
关于是否包含首屏所有的图片下载完成。这个网上有些争议,有的同学说不包含图片,只要DOM+样式 都渲染完了,就算完成了。
笔者认为,既然是首屏,那么首屏上所有的东西都加载完成,让用户感受不到还有没完成的部分,就算完成了。
所以,综合一下,咱们的首屏时间,包括首屏的DOM元素的渲染,展现在用户第一屏幕的所有图片都完成。
其实Chrome提供开发着检查网站整个渲染过程的小公举,哦不,是小工具(如图1.1.1所示)在F12开发者工具的Network面板里面:
图1.1.1
这个是屏幕捕获的工具,可以看到整个网页的渲染过程。我们接着来深究一下上述哪个时间点是首屏时间点。
我们来一起看看百度首页的首屏情况,由于百度首页加载比较快,所以这里咱们模拟一下3G网的延迟(如图1.1.2):
我们看到,虽然在240ms的时候,网页算是被渲染出来了,但是还是有很多空白的地方。
279MS的时候,虽然框架都被渲染完成了,DOM与样式也都渲染完成了,但是我们看到图片还不完整,所以,当然也不算首屏完成了。
有的同学会说,318ms的时候,总算完成了吧,nonono,我们向后观察,就会发现还有一些元素会再被渲染出来。也就是说知道稳定之前,我们都不能算首屏完成了。
知道487 ms的时候,页面才算加载完成了。并且之后不会再发生页面的抖动了。
看完这些,相信聪明的你心里已经有数了,什么是首屏时间。
1.2 白屏时间
这个其实不多说,读者也明白,就是页面处于空白的时间。页面空白,用户就会焦躁,并且变得不耐心。影响白屏时间的多数是:DNS解析耗时+服务端耗时+网络传输耗时。
1.3 用户可操作时间
顾名思义,这项指标值得是,我们的网页用户可以使用的时间。一般来讲 domready时间,便是我们的用户可操作时间了。
1.4 总下载时间
通常指,页面总体的下载时间,所有的页面资源都下载完成。
自定义指标
由于业务不同,站长们所关心的时间必然也不同了。比如你可能是一个电商网站的站长,你关心你的第一屏商品到底展示的有多快( 通常这会带来更多的收入),所以,你需要监控你的商品展现的时间。
如何统计自己网站的这些指标
2.1 如何统计首屏时间
其实,对于网页高度小于屏幕的网站来说,统计首屏时间非常的简单,只要在页面底部加上脚本打印当前时间即可,或者对于网页高度大于一屏的网页来说,只要在估算接近于一屏幕的元素的位置后,打印一下当前时间即可。
比如,现在你有一个简单的网页(如图2.1.1所示):
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0">
</head>
<body>
<div>这是第一屏,这是第一屏</div>
<img src="http://static.oschina.net/uploads/space/2016/0623/152644_6UUC_1177792.png">
<img src="http://static.oschina.net/uploads/space/2016/0623/152644_6UUC_1177792.png">
<img src="http://static.oschina.net/uploads/space/2016/0623/152644_6UUC_1177792.png">
<img src="http://static.oschina.net/uploads/space/2016/0623/152644_6UUC_1177792.png">
<div>第一屏结尾,第一屏结尾</div>
<img src="http://static.oschina.net/uploads/space/2016/0623/152644_6UUC_1177792.png">
<img src="http://static.oschina.net/uploads/space/2016/0623/152644_6UUC_1177792.png">
</body>
</html>
图2.1.1
我们需要统计首屏时间的话,则需要定义一个基准,就是--什么时候用户点开的当前网页,HTML5的performance接口提供了这个时间:performance.timing.navigationStart,这个就是用户访问我们网页最开始的跳转时间了。
<head>
<script type="text/javascript">
window.logInfo = {};
window.logInfo.openTime = performance.timing.navigationStart;
</script>
</head>
我们在页面开头处,将基准记下。
接下来,在大约的首屏处加上我们的统计:
<div>第一屏结尾,第一屏结尾</div>
<script type="text/javascript">
window.logInfo.firstScreen = +new Date() - window.logInfo.openTime;
console.log('首屏时间:', window.logInfo.firstScreen + 'ms');
</script>
图2.1.2
便有了首屏时间。
霸特,霸特。同学们不要激动的太早。我们这个首屏时间,并不没有算上图片。所以,我们得把首屏中所有图片的加载时间也算上。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0">
<script type="text/javascript">
window.logInfo = {};
window.logInfo.openTime = performance.timing.navigationStart;
</script>
</head>
<body>
<div>这是第一屏,这是第一屏</div>
<img src="http://static.oschina.net/uploads/space/2016/0623/152644_6UUC_1177792.png">
<img src="http://static.oschina.net/uploads/space/2016/0623/152644_6UUC_1177792.png">
<img src="http://static.oschina.net/uploads/space/2016/0623/152644_6UUC_1177792.png">
<img src="http://static.oschina.net/uploads/space/2016/0623/152644_6UUC_1177792.png">
<div>第一屏结尾,第一屏结尾</div>
<script type="text/javascript">
(function logFirstScreen() {
var images = document.getElementsByTagName('img');
var iLen = images.length;
var curMax = 0;
var inScreenLen = 0;
// 图片的加载回调
function imageBack() {
this.removeEventListener
&& this.removeEventListener('load', imageBack, !1);
if (++curMax === inScreenLen) {
// 如果所有在首屏的图片均已加载完成了的话,发送日志
log();
}
}
// 对于所有的位于指定区域的图片,绑定回调事件
for (var s = 0; s < iLen; s++) {
var img = images[s];
var offset = {
top: 0
};
var curImg = img;
while (curImg.offsetParent) {
offset.top += curImg.offsetTop;
curImg = curImg.offsetParent;
}
// 判断图片在不在首屏
if (document.documentElement.clientHeight < offset.top) {
continue;
}
// 图片还没有加载完成的话
if (!img.complete) {
inScreenLen++;
img.addEventListener('load', imageBack, !1);
}
}
// 如果首屏没有图片的话,直接发送日志
if (inScreenLen === 0) {
log();
}
// 发送日志进行统计
function log () {
window.logInfo.firstScreen = +new Date() - window.logInfo.openTime;
console.log('首屏时间:', window.logInfo.firstScreen + 'ms');
}
})();
</script>
<img src="http://static.oschina.net/uploads/space/2016/0623/152644_6UUC_1177792.png">
<img src="http://static.oschina.net/uploads/space/2016/0623/152644_6UUC_1177792.png">
</body>
</html>
以上封装的首屏时间函数,无依赖比较小巧,同学们可以直接使用于自己的项目中。这样,我们就轻轻松松的统计到了首屏时间。
2.2 如何统计白屏时间
可以在页面的head底部添加的JS代码来统计白屏时间,虽然这样做可能并不十分精准,但是也可以基本代表了首屏时间,如图2.2.1所示。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0">
<script type="text/javascript">
window.logInfo = {};
window.logInfo.openTime = performance.timing.navigationStart;
window.logInfo.whiteScreenTime = +new Date() - window.logInfo.openTime;
console.log('白屏时间:', window.logInfo.whiteScreenTime + 'ms');
</script>
</head>
2.3 如何统计用户可操作时间
前面提到过document.ready其实就可以算作我们的用户可操作时间啦。我们不妨直接试试,如图2.3.1所示:
document
.addEventListener(
'DOMContentLoaded',
function (event) {
window.logInfo.readyTime = +new Date() - window.logInfo.openTime;
console.log('用户可操作时间:', window.logInfo.readyTime);
}
);
如何打印总下载时间
页面总体下载时间,使用window.onload即可,这可以帮助我们看看我们所有的资源是否拖慢网页,如图2.4.1所示:
window.onload = function () {
window.logInfo.allloadTime = +new Date() - window.logInfo.openTime;
console.log('总下载时间:', window.logInfo.allloadTime + 'ms');
};
2.5 统一打印时间,更方便
我们将上述的统计合并,一个完整的统计就出来了,如图2.5.1所示:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0">
<script type="text/javascript">
window.logInfo = {};
window.logInfo.openTime = performance.timing.navigationStart;
window.logInfo.whiteScreenTime = +new Date() - window.logInfo.openTime;
</script>
</head>
<body>
<div>这是第一屏,这是第一屏</div>
<img src="http://static.oschina.net/uploads/space/2016/0623/152644_6UUC_1177792.png">
<img src="http://static.oschina.net/uploads/space/2016/0623/152644_6UUC_1177792.png">
<img src="http://static.oschina.net/uploads/space/2016/0623/152644_6UUC_1177792.png">
<img src="http://static.oschina.net/uploads/space/2016/0623/152644_6UUC_1177792.png">
<div>第一屏结尾,第一屏结尾</div>
<script type="text/javascript">
(function logFirstScreen() {
var images = document.getElementsByTagName('img');
var iLen = images.length;
var curMax = 0;
var inScreenLen = 0;
// 图片的加载回调
function imageBack() {
this.removeEventListener
&& this.removeEventListener('load', imageBack, !1);
if (++curMax === inScreenLen) {
// 如果所有在首屏的图片均已加载完成了的话,发送日志
log();
}
}
// 对于所有的位于指定区域的图片,绑定回调事件
for (var s = 0; s < iLen; s++) {
var img = images[s];
var offset = {
top: 0
};
var curImg = img;
while (curImg.offsetParent) {
offset.top += curImg.offsetTop;
curImg = curImg.offsetParent;
}
// 判断图片在不在首屏
if (document.documentElement.clientHeight < offset.top) {
continue;
}
// 图片还没有加载完成的话
if (!img.complete) {
inScreenLen++;
img.addEventListener('load', imageBack, !1);
}
}
// 如果首屏没有图片的话,直接发送日志
if (inScreenLen === 0) {
log();
}
// 发送日志进行统计
function log () {
window.logInfo.firstScreen = +new Date() - window.logInfo.openTime;
}
})();
document
.addEventListener(
'DOMContentLoaded',
function (event) {
window.logInfo.readyTime = +new Date() - window.logInfo.openTime;
}
);
window.onload = function () {
window.logInfo.allloadTime = +new Date() - window.logInfo.openTime;
var timname = {
whiteScreenTime: '白屏时间',
firstScreen: '首屏时间',
readyTime: '用户可操作时间',
allloadTime: '总下载时间'
};
for (var i in timname) {
console.log(timname[i] + ':' + window.logInfo[i] + 'ms');
}
};
</script>
<img src="http://static.oschina.net/uploads/space/2016/0623/152644_6UUC_1177792.png">
<img src="http://static.oschina.net/uploads/space/2016/0623/152644_6UUC_1177792.png">
</body>
</html>