ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

首屏加载时间计算

2022-06-06 12:04:59  阅读:187  来源: 互联网

标签:function return target detail ele 计算 const 首屏 加载


文章:https://cloud.tencent.com/developer/article/1850013

 

function getFirstScreenTime() {
const details = [];
return new Promise(function (resolve, reject) {
// 5s之内先收集所有的dom变化,并以key(时间戳)、value(dom list)的结构存起来。

const observeDom = observeDoc(details);

setTimeout(function () {
observeDom.disconnect();
console.log('details', details);
resolve(details);
}, 5000);
}).then(function (details) {
return compareTime(details);
});
}

// 监听文档
function observeDoc(details) {
var observeDom = new MutationObserver(function (mutations) {
if (!mutations || !mutations.forEach) return;
var detail = {
time: performance.now(),
roots: [],
imgs: [],
};

mutations.forEach(function (mutation) {
if (!mutation || !mutation.addedNodes || !mutation.addedNodes.forEach) {
return;
}
mutation.addedNodes.forEach(function (ele) {
const nodeName = ele.nodeName.toLocaleLowerCase();
const isImg = nodeName === 'img';
const isValidEle = isEleValid(ele, detail.roots);
if (isValidEle) {
detail.roots.push(ele);
if (isImg) {
detail.imgs.push(ele);
}
}
});
});
if (detail.roots.length) {
details.push(detail);
}
});
observeDom.observe(document, {
childList: true,
subtree: true,
});
return observeDom;
}

// 比较首屏内DOM时间
function compareTime(details) {
// 分析上面收集到的数据,返回最终的结果
const domRenderTime = [];
const allImgs = [];
const allImgLoadTimes = [];

details.forEach(function (detail) {
// 拿到所有首屏DOM 的 渲染时间
for (var i = 0; i < detail.roots.length; i++) {
const ele = detail.roots[i];
if (isInFSAndVisible(ele)) {
domRenderTime.push(detail.time);
// 同一个 detail 的 节点,时间一样,不用继续收集了
break;
}
}

// 拿到所有首屏中的图片
for (var i = 0; i < detail.imgs.length; i++) {
const ele = detail.imgs[i];
if (isInFSAndVisible(ele)) {
allImgs.push(ele.src);
}
}
});

// 遍历当前请求的图片中,如果有开始请求时间在首屏dom渲染期间的,则表明该图片是首屏渲染中的一部分,
// 所以dom渲染时间和图片返回时间中大的为首屏渲染时间
window.performance.getEntriesByType('resource').forEach(function (resource) {
const url = resource.name;
if (resource.initiatorType === 'img' && allImgs.indexOf(url) > -1) {
allImgLoadTimes.push(resource.responseEnd);
}
});

console.log('allImgs', allImgs);
console.log('domRenderTime', domRenderTime);
console.log('allImgLoadTimes', allImgLoadTimes);

const resultTime = Math.max(...domRenderTime, ...allImgLoadTimes);

return resultTime;
}

// 节点是否有效
function isEleValid(ele, arr) {
const ignoreEleList = ['script', 'style', 'link', 'br'];
const nodeName = ele.nodeName.toLocaleLowerCase();
const isEleNode = ele.nodeType === 1;
const isRenderNode = ignoreEleList.indexOf(nodeName) !== -1;
if (isEleNode && isRenderNode) {
if (isInFS(ele)) {
if (!isElderOrExitEle(ele, arr)) {
return true;
}
}
}
return false;
}

// dom 是否有效,过滤
function isEleValid(ele, arr) {
const ignoreEleList = ['script', 'style', 'link', 'br'];
const nodeName = ele.nodeName.toLocaleLowerCase();
const isEleNode = ele.nodeType === 1;
const isRenderNode = ignoreEleList.indexOf(nodeName) === -1;
if (isEleNode && isRenderNode) {
if (isInFS(ele)) {
if (!isElderOrExitEle(ele, arr)) {
return true;
}
// 图片另算
else if (nodeName === 'img') {
return true;
}
}
}
return false;
}

// 是否已经存在节点,或者是长辈节点
function isElderOrExitEle(target, arr) {
if (!target || target === document.documentElement) {
return false;

// 说明数组已经存在这个节点
} else if (arr.indexOf(target) !== -1) {
return true;

// 不要长辈节点
} else {
return isElderOrExitEle(target.parentElement, arr);
}
}

// 位置是否首屏中
function isInFS(target) {
if (!target || !target.getBoundingClientRect) return false;
var rect = target.getBoundingClientRect(),
screenHeight = window.innerHeight,
screenWidth = window.innerWidth;
return (
rect.left >= 0 &&
rect.left < screenWidth &&
rect.top >= 0 &&
rect.top < screenHeight
);
}

// 首屏中,并且可见
function isInFSAndVisible(target) {
if (!target || !target.getBoundingClientRect) return false;
var rect = target.getBoundingClientRect();
const isvisible = isVisible(target);
const hasArea = rect.width > 0 && rect.height > 0;

return isInFS(target) && hasArea && isvisible;
}

// 是否可见
function isVisible(target) {
target.style.opacity = 'inherit';
var rawOpacity = getStyle(target, 'opacity');
var visibility = getStyle(target, 'visibility');

var opacity = +rawOpacity;
if (opacity != rawOpacity) {
opacity = 1; // can not check old browser
}
if (opacity > 0.09 || visibility === 'visible') {
return true;
}
return false;
}

// 获取样式
function getStyle(el, name) {
if (window.getComputedStyle) {
return getComputedStyle(el, null)[name];
}
if (el.currentStyle) {
return el.currentStyle[name];
}
}

标签:function,return,target,detail,ele,计算,const,首屏,加载
来源: https://www.cnblogs.com/zerofan/p/16347683.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有