参考
把前端性能监控做到极致 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 (兼容)
