window.performance
是W3C性能小组引入的新的API,目前IE9以上的浏览器都支持。一个performance对象的完整结构以下图所示:
javascript
memory
字段表明JavaScript对内存的占用。css
navigation
字段统计的是一些网页导航相关的数据:html
redirectCount
:重定向的数量(只读),可是这个接口有同源策略限制,即仅能检测同源的重定向;最重要的是timing
字段的统计数据,它包含了网络、解析等一系列的时间数据。java
2.2.1 timing
APIweb
timing
的总体结构以下图所示:bootstrap
各字段的含义以下:api
startTime
:有些浏览器实现为navigationStart
,表明浏览器开始unload前一个页面文档的开始时间节点。好比咱们当前正在浏览baidu.com,在地址栏输入google.com并回车,浏览器的执行动做依次为:unload当前文档(即baidu.com)->请求下一文档(即google.com)。navigationStart的值即是触发unload当前文档的时间节点。数组
若是当前文档为空,则navigationStart的值等于fetchStart。浏览器
redirectStart
和redirectEnd
:若是页面是由redirect而来,则redirectStart和redirectEnd分别表明redirect开始和结束的时间节点;unloadEventStart
和unloadEventEnd
:若是前一个文档和请求的文档是同一个域的,则unloadEventStart
和unloadEventEnd
分别表明浏览器unload前一个文档的开始和结束时间节点。不然二者都等于0;fetchStart
是指在浏览器发起任何请求以前的时间值。在fetchStart和domainLookupStart
之间,浏览器会检查当前文档的缓存;domainLookupStart
和domainLookupEnd
分别表明DNS查询的开始和结束时间节点。若是浏览器没有进行DNS查询(好比使用了cache),则二者的值都等于fetchStart
;connectStart
和connectEnd
分别表明TCP创建链接和链接成功的时间节点。若是浏览器没有进行TCP链接(好比使用持久化链接webscoket),则二者都等于domainLookupEnd
;secureConnectionStart
:可选。若是页面使用HTTPS,它的值是安全链接握手以前的时刻。若是该属性不可用,则返回undefined。若是该属性可用,但没有使用HTTPS,则返回0;requestStart
表明浏览器发起请求的时间节点,请求的方式能够是请求服务器、缓存、本地资源等;responseStart
和responseEnd
分别表明浏览器收到从服务器端(或缓存、本地资源)响应回的第一个字节和最后一个字节数据的时刻;domLoading
表明浏览器开始解析html文档的时间节点。咱们知道IE浏览器下的document有readyState
属性,domLoading
的值就等于readyState
改变为loading
的时间节点;domInteractive
表明浏览器解析html文档的状态为interactive
时的时间节点。domInteractive
并不是DOMReady,它早于DOMReady触发,表明html文档解析完毕(即dom tree建立完成)可是内嵌资源(好比外链css、js等)还未加载的时间点;domContentLoadedEventStart
:表明DOMContentLoaded
事件触发的时间节点:缓存
页面文档彻底加载并解析完毕以后,会触发DOMContentLoaded事件,HTML文档不会等待样式文件,图片文件,子框架页面的加载(load事件能够用来检测HTML页面是否彻底加载完毕(fully-loaded))。
domContentLoadedEventEnd
:表明DOMContentLoaded
事件完成的时间节点,此刻用户能够对页面进行操做,也就是jQuery中的domready时间;domComplete
:html文档彻底解析完毕的时间节点;loadEventStart
和loadEventEnd
分别表明onload事件触发和结束的时间节点
2.2.2 计算性能指标
可使用Navigation.timing
统计到的时间数据来计算一些页面性能指标,好比DNS查询耗时、白屏时间、domready等等。以下:
因此根据上面的时间点,咱们能够计算常规的性能值,以下:
(使用该api时须要在页面彻底加载完成以后才能使用,最简单的办法是在window.onload事件中读取各类数据,由于不少值必须在页面彻底加载以后才能得出。)
var timing = window.performance && window.performance.timing;
var navigation = window.performance && window.performance.navigation;
重定向次数:
var redirectCount = navigation && navigation.redirectCount;
跳转耗时:
var redirect = timing.redirectEnd - timing.redirectStart;
APP CACHE 耗时:
var appcache = Math.max(timing.domainLookupStart - timing.fetchStart, 0);
DNS 解析耗时:
var dns = timing.domainLookupEnd - timing.domainLookupStart;
TCP 连接耗时:
var conn = timing.connectEnd - timing.connectStart;
等待服务器响应耗时(注意是否存在cache):
var request = timing.responseStart - timing.requestStart;
内容加载耗时(注意是否存在cache):
var response = timing.responseEnd - timing.responseStart;
整体网络交互耗时,即开始跳转到服务器资源下载完成:
var network = timing.responseEnd - timing.navigationStart;
渲染处理:
var processing = (timing.domComplete || timing.domLoading) - timing.domLoading;
抛出 load 事件:
var load = timing.loadEventEnd - timing.loadEventStart;
总耗时:
var total = (timing.loadEventEnd || timing.loadEventStart || timing.domComplete || timing.domLoading) - timing.navigationStart;
可交互:
var active = timing.domInteractive - timing.navigationStart;
请求响应耗时,即 T0,注意cache:
var t0 = timing.responseStart - timing.navigationStart;
首次出现内容,即 T1:
var t1 = timing.domLoading - timing.navigationStart;
内容加载完毕,即 T3:
var t3 = timing.loadEventEnd - timing.navigationStart;
复制代码
2.2.3 Resource timing API
Resource timing API是用来统计静态资源相关的时间信息,详细的内容请参考W3C Resource timing。这里咱们只介绍performance.getEntries
方法,它能够获取页面中每一个静态资源的请求,【以百度移动版首页的logo为例】以下:
能够看到performance.getEntries
返回一个数组,数组的每一个元素表明对应的静态资源的信息,好比上图展现的第一个元素对应的资源类型initiatorType
是图片img
,请求花费的时间就是duration
的值。
关于Resource timing API的使用场景,感兴趣的同窗能够深刻研究。
;
(function() {
handleAddListener('load', getTiming)
function handleAddListener(type, fn) {
if(window.addEventListener) {
window.addEventListener(type, fn)
} else {
window.attachEvent('on' + type, fn)
}
}
function getTiming() {
try {
var time = performance.timing;
var timingObj = {};
var loadTime = (time.loadEventEnd - time.loadEventStart) / 1000;
if(loadTime < 0) {
setTimeout(function() {
getTiming();
}, 200);
return;
}
timingObj['重定向时间'] = (time.redirectEnd - time.redirectStart) / 1000;
timingObj['DNS解析时间'] = (time.domainLookupEnd - time.domainLookupStart) / 1000;
timingObj['TCP完成握手时间'] = (time.connectEnd - time.connectStart) / 1000;
timingObj['HTTP请求响应完成时间'] = (time.responseEnd - time.requestStart) / 1000;
timingObj['DOM开始加载前所花费时间'] = (time.responseEnd - time.navigationStart) / 1000;
timingObj['DOM加载完成时间'] = (time.domComplete - time.domLoading) / 1000;
timingObj['DOM结构解析完成时间'] = (time.domInteractive - time.domLoading) / 1000;
timingObj['脚本加载时间'] = (time.domContentLoadedEventEnd - time.domContentLoadedEventStart) / 1000;
timingObj['onload事件时间'] = (time.loadEventEnd - time.loadEventStart) / 1000;
timingObj['页面彻底加载时间'] = (timingObj['重定向时间'] + timingObj['DNS解析时间'] + timingObj['TCP完成握手时间'] + timingObj['HTTP请求响应完成时间'] + timingObj['DOM结构解析完成时间'] + timingObj['DOM加载完成时间']);
for(item in timingObj) {
console.log(item + ":" + timingObj[item] + '毫秒(ms)');
}
console.log(performance.timing);
} catch(e) {
console.log(timingObj)
console.log(performance.timing);
}
}
})();
复制代码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<link rel="stylesheet" type="text/css" href="//cdn.bootcss.com/bootstrap/4.0.0-alpha.6/css/bootstrap.css" />
<script src=""></script>
<script type="text/javascript" src=""></script>
</head>
<body>
</body>
</html>
复制代码