导航时间接口

497 阅读3分钟

简介

导航时间接口(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经历如下阶段:

企业微信截图_16294661032971.png 【注意】括号内的特性在不同源的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 参考