如何确定首屏加载时间?
首屏时间的定义:
浏览器显示第一屏页面所消耗的时间,以 800x600 像素尺寸为标准,从开始加载到浏览器页面显示高度达到 600 像素且此区域有内容显示的时间。
也就是说用户能够看到区域内所有元素加载完的时间。
一个页面的“总加载时间”要比“首屏时间”长,但对于最终用户体验而言,当内容充满首屏的区域时,用户就可以看到网站的主要内容并可以进行各自的选择了。首屏时间的快与慢,直接影响到了用户对网站的认知度
对于页面的加载时间,dom 都提供了 api 接口,比如,整个页面 dom 树的构建时间,我们通过打点 DOMContentLoaded,就能得到。整个页面加载完成,包括图片,视频等外部资源,我们通过 window.onload 的方法也可以得到。但是对于首屏,没有这样的接口提供。
那么如何去计算首屏的加载时间?
首先要解决的问题是哪些属于首屏的内容。由于手机屏幕尺寸的多样性,同一页面在手机屏幕上用户所能看到的首屏内容有可能不一样。所以需要去判断哪些元素属于首屏元素并且该元素加载是否完成。对于非可替换元素,dom 的加载完成说明了该元素已经完成加载,而对于一些可替换元素,如 img 标签,需要外部资源的加载完成才能有实际内容的展示,而页面耗时最大的部分也是这些外部资源的加载。
因为通常需要考虑首屏时间的页面,都是因为在首屏位置内放入了较多的图片资源。现代浏览器处理图片资源时是异步的,会先将图片长宽应用于页面排版,然后随着收到图片数据由上至下绘制显示的。并且浏览器对每个页面的 TCP 连接数限制,使得并不是所有图片都能立刻开始下载和显示。
- 因此我们在 DOM 树构建完成后即可遍历获得所有在设备屏幕高度内的所有图片资源标签,
- 在所有图片标签中添加 document.onload 事件,
- 在整页加载完成(window.onLoad 事件发生)时遍历图片标签并获得之前注册的 document.onload 事件时间的最大值,
- 该最大值减去 navigationStart 即认为近似的首屏时间。
- 而对于页面没有图片的页面,我们可以近似认为首屏的加载时间为 dom 完成的时间
function firstScreen() {
//收集所有页面的加载时间
var imgs = document.getElementsByTagName("img");
var fsItems = [];
var loadEvent = function () {
//gif避免
if (this.removeEventListener) {
this.removeEventListener("load", loadEvent, false);
}
var curTime = +new Date();
fsItems.push({
img: this,
time: curTime,
});
};
for (var i = 0; i < imgs.length; i++) {
(function () {
var img = imgs[i];
if (img.addEventListener) {
// complete只是HTMLImageElement对象的一个属性,而onload则是这个Image对象的load事件回调,前者不能准确的在事件发生时进行异步回调并且、在浏览器的兼容性上也有些问题。
!img.complete && img.addEventListener("load", loadEvent, false);
} else if (img.attachEvent) {
// 兼容 ie
img.attachEvent("onreadystatechange", function () {
if (img.readyState == "complete") {
loadEvent.call(img, loadEvent);
}
});
}
})();
}
//获取元素在dom中的位置
function getOffsetTop(elem) {
var top = 0;
top = window.pageYOffset
? window.pageYOffset
: document.documentElement.scrollTop;
top += elem.getBoundingClientRect().top;
return top;
}
function findMaxTime() {
var sh = document.documentElement.clientHeight,
maxTime = 0;
for (var i = 0; i < fsItems.length; i++) {
var item = fsItems[i],
img = item["img"],
time = item["time"],
top = getOffsetTop(img);
if (top > 0 && top < sh) {
//找首屏中的图片
maxTime = time > maxTime ? time : maxTime;
}
}
return maxTime;
}
window.addEventListener("load", function () {
var imgTime = findMaxTime(),
domTime = window.performance.timing.domInteractive, //dom完成时间
speedTime,
startTime =
window.performance.timing.navigationStart ||
window.performance.timing.startTime, //页面首页时间
screenTime = imgTime > 0 ? imgTime : domTime; //如果没有图片,直接取dom时间
speedTime = screenTime - startTime;
console.log(speedTime);
});
}
firstScreen();
如何得到图片的最后加载时间
- 获取页面所有图片
- 计算在 图片 load 事件中,获取到当前 日期毫秒值
- 得到最后一次的毫秒值,即 图片的最后加载时间