参考
把前端性能监控做到极致 PPT
大前端时代前端监控的最佳实践 (gmtc视频) PPT 和 文章
如何计算首屏加载时间?
GMTC2018 《大前端时代前端监控的最佳实践》 彭伟春myslide.cn.pdf
1 发展阶段
1.1 手动打点
比如以前一个项目就是手动打点,时间截取根据项目特性定,比如页面展示依赖接口,则一般在js把数据插入页面才算页面结束时间,但是这可能就不是首屏时间,这个首屏时间其实没有统一的规定。
// 页头
<head>
<meta charset="UTF-8">
<script type="text/javascript">
sessionStorage.setItem('startHtmlTime',new Date().getTime());
</script>
<title>xxxxxx</title>
<link rel="stylesheet" href="css/swiper.min.css">
.......
</head>
// 页尾
<script src="js/lib/swiper.min.js"></script>
<script type="text/javascript" src="js/lib/sea.js"></script>
<script>
seajs.config({
base: "./js/",
alias: {
"zepto": "lib/zepto.js"
}
});
seajs.use("index.js");
sessionStorage.setItem('endHtmlTime',new Date().getTime());
</script>
</body>
</html>
// 页面加载完成后数据上报
exports.getSessionTime = function(async){
var userGid =sessionStorage.getItem(config.USERGID_KEY);
var pageEle=document.querySelector("[id^=xxx_acv]");
var pageId=(pageEle&&pageEle.id)||"";
var zuid=getStoreUuid();
var timeParams = {
"mid":"ACQ04",
"appid":appflag,
"ugid": userGid || "",
"ctime": new Date().getTime(),
"zuid": zuid,
"eleId":pageId,
"pageId":pageId,
"path":window.location.pathname,
"startHtmlTime" : sessionStorage.getItem("startHtmlTime"),
"endHtmlTime" : sessionStorage.getItem("endHtmlTime"),
"jsRealyTime" : sessionStorage.getItem("jsRealyTime"),
"loadingHideTime" : sessionStorage.getItem("loadingHideTime"),
"htmlDuaration":sessionStorage.getItem("endHtmlTime")-sessionStorage.getItem("startHtmlTime"),//html加载时间
"applyDuaration":sessionStorage.getItem("jsRealyTime")-sessionStorage.getItem("endHtmlTime"),//js加载时间
"jsDuaration":sessionStorage.getItem("loadingHideTime")-sessionStorage.getItem("jsRealyTime")//接口加载时间
};
$.ajax({
url:config.ACQUISIURL+"zuid="+encodeURI(zuid)+"&appid="+appflag,
type:'post',
data:JSON.stringify(timeParams),
async:async,
dataType:'json',
contentType:'application/json;charset=UTF-8;',
success:function(data){
}
})
};
1.2 标准API
Performance API
比如:(注意:performance.timing api将要被废弃)
if (!!window.performance) {
var _PerforMance = window.performance;
var _Timing = _PerforMance.timing;
if (_Timing) {
var loadAcData = {
mid: _this.store.storeTiming,
startTime: _this.util.getTimeStr(),
path: _this.util.getCookie(_this.store.storePage),
connectEnd : _Timing.connectEnd, //返回浏览器与服务器之间的连接建立时的Unix毫秒时间戳
connectStart : _Timing.connectStart, //返回HTTP请求开始向服务器发送时的Unix毫秒时间戳
domComplete:_Timing.domComplete,//返回当前文档解析完成时的Unix毫秒时间戳。
domContentLoadedEventEnd : _Timing.domContentLoadedEventEnd,//返回当所有需要立即执行的脚本已经被执行(不论执行顺序)时的Unix毫秒时间戳。
domContentLoadedEventStart : _Timing.domContentLoadedEventStart,//返回当解析器发送DOMContentLoaded 事件,即所有需要被执行的脚本已经被解析时的Unix毫秒时间戳。
domInteractive : _Timing.domInteractive,//返回当前网页DOM结构结束解析、开始加载内嵌资源时的Unix毫秒时间戳。
domLoading : _Timing.domLoading,//返回当前网页DOM结构开始解析的Unix毫秒时间戳。
domainLookupEnd: _Timing.domainLookupEnd, //表征了域名查询结束的UNIX时间戳。
domainLookupStart: _Timing.domainLookupStart, //表征了域名查询开始的UNIX时间戳。
fetchStart: _Timing.fetchStart, //表征了浏览器准备好使用HTTP请求来获取(fetch)文档的UNIX时间戳。这个时间点会在检查任何应用缓存之前。
loadEventEnd: _Timing.loadEventEnd,//返回当load事件结束,即加载事件完成时的Unix毫秒时间戳。
loadEventStart: _Timing.loadEventStart,//load事件被发送时的Unix毫秒时间戳。
navigationStart: _Timing.navigationStart,//准备加载新页面的起始时间
redirectEnd: _Timing.redirectEnd, //表征了最后一个HTTP重定向完成时(也就是说是HTTP响应的最后一个比特直接被收到的时间)的UNIX时间戳
redirectStart: _Timing.redirectStart, //表征了第一个HTTP重定向开始时的UNIX时间戳
requestStart: _Timing.requestStart,//返回浏览器向服务器发出HTTP请求时(或开始读取本地缓存时)的Unix毫秒时间戳。
responseEnd: _Timing.responseEnd,//返回浏览器从服务器收到(或从本地缓存读取,或从本地资源读取)最后一个字节时的Unix毫秒时间戳。
responseStart: _Timing.responseStart,//返回浏览器从服务器收到(或从本地缓存读取)第一个字节时的Unix毫秒时间戳
secureConnectionStart: _Timing.secureConnectionStart, //浏览器与服务器开始安全链接的握手时的Unix毫秒时间戳
unloadEventEnd: _Timing.unloadEventEnd, //表征了unload事件处理完成时的UNIX时间戳
unloadEventStart: _Timing.unloadEventStart //表征了unload事件抛出时的UNIX时间戳
};
loadAcData.DNS = _Timing.domainLookupEnd - _Timing.domainLookupStart; //DNS查询时间
loadAcData.TCP = _Timing.connectEnd - _Timing.connectStart; //TCP连接耗时
loadAcData.WT = _Timing.responseStart - _Timing.navigationStart; //白屏时间
loadAcData.PRDOM = _Timing.domComplete - _Timing.responseEnd; //dom解析耗时
loadAcData.ONL = _Timing.loadEventEnd - _Timing.loadEventStart; //执行onload事件耗时
loadAcData.DR = _Timing.domContentLoadedEventEnd - _Timing.navigationStart; //dom ready时间,脚本加载完成时间
loadAcData.ALLRT = _Timing.responseEnd - _Timing.requestStart; //所有请求耗时
loadAcData.FXHR = _Timing.fetchStart - _Timing.navigationStart; //第一个请求发起时间
this.util.setCookie(this.store.storeTiming, JSON.stringify(ACPdata));
}
对于查看首屏渲染时间,可以使用devtool查看这个时间,现代浏览器也有DOMContentLoaded事件,这个在ssr渲染模式下参考价值才大。
1.3 SPA阶段-标准无意义
SPA页面一般只存在几个简单的元素,然后由js调用ajax拿到数据再向页面插入内容,这种模式下,w3c的标准就不在准确
1.4 FMP
没有标准API支持,通过算法计算
如
可以在lighthouse报告中看到,First Meaningful Paint
更多的需要去监听计算来确认FMP的时间,比如视频中的FMP量化方式
另外一个分享
影子-如何量化页面FMP .pdf
2 监控模式
2.1 合成监控—-lighthouse / webpagetest
2.2 实时(真实)监控——埋点/性能/行为/错误/设备等数据上报
3 选择合适指标
4 埋点
埋点(无埋点/坑位)
数据内容
页面卸载数据上报
Navigator.sendBeacon() / img (兼容)