简介
导航时间接口(Navigation Timing level 2)规范定义了用于访问文档的完整时间信息的Web应用程序接口:PerformanceNavigationTiming
Navigation Timing现状:
- Navigation Timing Level 2 定义的PerformanceNavigationTiming接口实现为:window.performance.getEntriesByType('navigation')[0]
- Navigation Timing Level 1定义的 PerformanceTiming 接口实现已标志为**Obselete**状态,但目前浏览器仍保留其接口实现,即window.performance.timing.
Navigation Timing Level 2事件模型
每个document经历如下阶段:
【注意】括号内的特性在不同源的document访问中可能不可用
在浏览器中的控制台中,可通过以下接口查看
// level 2:
// performance.getEntries()[0] // document为第一个导航元素
// performance.getEntriesByType('navigation')[0]
// level 1:
// performance.timing
定义对象
PerformanceNavigationTiming
数据结构(level 2)
interface PerformanceNavigationTiming : PerformanceResourceTiming {
// implement PerformanceEntry
// name : 访问的url地址
// entryType : navigation
// startTime : 访问的起始时间, 0
// duration : startTime至loadEventEnd的时间段
// implement PerformanceResourceTiming
// workerStart : service worker 计时
// fetchStart : service worker fetch 事件触发的时间
// 前以一个网页(document)的卸载时间,如果无前一个网页 unload 或者前一个网页与当前页面不同源,则为0
readonly attribute DOMHighResTimeStamp unloadEventStart;
// 当unload绑定事件执行完毕。如果没有前一个页面 或 前一个页面重定向是不同源的,则为0
readonly attribute DOMHighResTimeStamp unloadEventEnd;
// 解析完document的时间,将执行script列表不为空,Document.readyState变为interactive的时间,之后触发readystatechange事件
readonly attribute DOMHighResTimeStamp domInteractive;
// DOM解析完成后、将执行script列表为空,第一次开始处理dom操作队列的任务时。该dom开始加载至全局window的时间,DOMContentLoaded事件抛出前
readonly attribute DOMHighResTimeStamp domContentLoadedEventStart;
// 该dom已加载至全局window的时间,DOMContentLoaded事件抛出后
readonly attribute DOMHighResTimeStamp domContentLoadedEventEnd;
// 第二次处理dom操作队列的任务,dom加载至window的document中,触发window的load事件之后, Document.readyState变为complete,触发readystatechange事件
readonly attribute DOMHighResTimeStamp domComplete;
// 当前文档的load事件触发时间,若load没触发返回则返回0
readonly attribute DOMHighResTimeStamp loadEventStart;
// 当文档的load事件回调执行完毕时,若事件没触发或没有完成,则返回0
readonly attribute DOMHighResTimeStamp loadEventEnd;
// type : 根据history handling behavior标识
// "navigate" : history正常增加新记录,即通过default(直接访问) 或 (history)replace访问,且标签没有设置rel="prerender"属性
// "reload" : 表示重新加载当前页面
// "back_forward" : 返回history已有记录的页面
// "prerender" : 有rel="prerender"属性的资源
readonly attribute NavigationType type;
// 表示在到达这个页面之前重定向了多少次
readonly attribute unsigned short redirectCount;
[Default] object toJSON();
};
【注意】括号内的特性在不同源的document访问中可能不可用* .
基本使用
// 只有一个 PerformanceNavigationTiming 对象在性能时间轴内
const [entry] = performance.getEntriesByType("navigation");
console.table(entry.toJSON());
性能计算
function getPerformanceTiming () {
const performance = window.performance
if (!performance) return
const nav = performance.getEntriesByType('navigation')[0]
const t = performance.timing;
const times = {}
//【重要】页面加载完成的时间, 即用户等待页面可用的时间
times.loadPage = nav.duration // nav.loadEventEnd - nav.startTime
//【重要】解析 DOM 树结构的时间
times.domReady = nav.domComplete - nav.responseEnd;
//【重要】重定向的时间
//【注意】拒绝重定向!比如,http://example.com/ 就不该写成 http://example.com
times.redirect = nav.redirectEnd - nav.redirectStart;
//【重要】DNS 查询时间
//【原因】DNS 预加载做了么?页面内是不是使用了太多不同的域名导致域名查询的时间太长?
// 可使用 HTML5 Prefetch 预查询 DNS ,见:[HTML5 prefetch](http://segmentfault.com/a/1190000000633364)
times.lookupDomain = nav.domainLookupEnd - nav.domainLookupStart;
//【重要】读取页面第一个字节的时间
times.ttfb = nav.responseStart - nav.navigationStart;
//【重要】内容加载完成的时间
//【原因】页面内容经过 gzip 压缩了么,静态资源 css/js 等压缩了么?
times.request = nav.responseEnd - nav.requestStart;
//【重要】执行 onload 回调函数的时间
//【原因】是否太多不必要的操作都放到 onload 回调函数里执行了,考虑过延迟加载、按需加载的策略么?
times.loadEvent = nav.loadEventEnd - nav.loadEventStart;
// DNS 缓存时间
times.appcache = nav.domainLookupStart - nav.fetchStart;
// 卸载页面的时间
times.unloadEvent = nav.unloadEventEnd - nav.unloadEventStart;
// TCP 建立连接完成握手的时间
times.connect = nav.connectEnd - nav.connectStart;
return times;
}
PerformanceNavigationTiming(level 1:Obselete)
performance.timing 请查看PerformanceNavigationTiming 参考
参考文献/网页:
Web_Performance概览
Navigation Timing Level 2
MDN Web Docs performance API
PerformanceNavigationTiming 参考