Chrome 64 即将弃用 chrome.loadTimes() API

chrome.loadTimes() 是一个非标准 API,公开了加载指标和 网络信息,以帮助开发者更好地了解自己的 网站在现实中的性能

由于该 API 是在 2009 年推出的,因此它报告的所有有用信息都可以 例如:

这些标准化 API 目前由多个浏览器供应商实施。作为 因此,Chrome 64 将弃用 chrome.loadTimes()

已废弃的 API

chrome.loadTimes() 函数会返回单个对象,其中包含其所有 加载和网络信息。例如,以下对象是 在 www.google.com 上调用 chrome.loadTimes() 的过程:

{
  "requestTime": 1513186741.847,
  "startLoadTime": 1513186741.847,
  "commitLoadTime": 1513186742.637,
  "finishDocumentLoadTime": 1513186742.842,
  "finishLoadTime": 1513186743.582,
  "firstPaintTime": 1513186742.829,
  "firstPaintAfterLoadTime": 0,
  "navigationType": "Reload",
  "wasFetchedViaSpdy": true,
  "wasNpnNegotiated": true,
  "npnNegotiatedProtocol": "h2",
  "wasAlternateProtocolAvailable": false,
  "connectionInfo": "h2"
}

标准化换货

现在,您可以使用标准化 API 找到上述每个值。以下 表将每个值与其标准化 API 进行匹配,以下部分显示 代码示例,说明如何使用最新的等效方法在旧版 API 中获取每个值。

chrome.loadTimes() 个地图项 标准化 API 替换
requestTime <ph type="x-smartling-placeholder"></ph> 导航计时 2
startLoadTime <ph type="x-smartling-placeholder"></ph> 导航计时 2
commitLoadTime <ph type="x-smartling-placeholder"></ph> 导航计时 2
finishDocumentLoadTime <ph type="x-smartling-placeholder"></ph> 导航计时 2
finishLoadTime <ph type="x-smartling-placeholder"></ph> 导航计时 2
firstPaintTime <ph type="x-smartling-placeholder"></ph> 绘制时间
firstPaintAfterLoadTime 不适用
navigationType <ph type="x-smartling-placeholder"></ph> 导航计时 2
wasFetchedViaSpdy <ph type="x-smartling-placeholder"></ph> 导航计时 2
wasNpnNegotiated <ph type="x-smartling-placeholder"></ph> 导航计时 2
npnNegotiatedProtocol <ph type="x-smartling-placeholder"></ph> 导航计时 2
wasAlternateProtocolAvailable 不适用
connectionInfo <ph type="x-smartling-placeholder"></ph> 导航计时 2

下面的代码示例返回的值与通过 chrome.loadTimes()。不过,对于新代码,这些代码示例 建议。原因在于 chrome.loadTimes() 以秒表示的纪元时间表示时间值,而新的性能 API 通常以毫秒为单位报告网页 <时间来源>,它往往 对性能分析更为有用。

多个示例还青睐 Performance Timeline 2 API(例如 performance.getEntriesByType()),但要为旧版 API 提供回退机制, Navigation Timing 1 API 本身 浏览器支持范围更广今后,建议使用 Performance Timeline API 并且通常以更高的精度报告。

requestTime

function requestTime() {
  // If the browser supports the Navigation Timing 2 and HR Time APIs, use
  // them, otherwise fall back to the Navigation Timing 1 API.
  if (window.PerformanceNavigationTiming && performance.timeOrigin) {
    const ntEntry = performance.getEntriesByType('navigation')[0];
    return (ntEntry.startTime + performance.timeOrigin) / 1000;
  } else {
    return performance.timing.navigationStart / 1000;
  }
}

startLoadTime

function startLoadTime() {
  // If the browser supports the Navigation Timing 2 and HR Time APIs, use
  // them, otherwise fall back to the Navigation Timing 1 API.
  if (window.PerformanceNavigationTiming && performance.timeOrigin) {
    const ntEntry = performance.getEntriesByType('navigation')[0];
    return (ntEntry.startTime + performance.timeOrigin) / 1000;
  } else {
    return performance.timing.navigationStart / 1000;
  }
}

commitLoadTime

function commitLoadTime() {
  // If the browser supports the Navigation Timing 2 and HR Time APIs, use
  // them, otherwise fall back to the Navigation Timing 1 API.
  if (window.PerformanceNavigationTiming && performance.timeOrigin) {
    const ntEntry = performance.getEntriesByType('navigation')[0];
    return (ntEntry.responseStart + performance.timeOrigin) / 1000;
  } else {
    return performance.timing.responseStart / 1000;
  }
}

finishDocumentLoadTime

function finishDocumentLoadTime() {
  // If the browser supports the Navigation Timing 2 and HR Time APIs, use
  // them, otherwise fall back to the Navigation Timing 1 API.
  if (window.PerformanceNavigationTiming && performance.timeOrigin) {
    const ntEntry = performance.getEntriesByType('navigation')[0];
    return (ntEntry.domContentLoadedEventEnd + performance.timeOrigin) / 1000;
  } else {
    return performance.timing.domContentLoadedEventEnd / 1000;
  }
}

finishLoadTime

function finishLoadTime() {
  // If the browser supports the Navigation Timing 2 and HR Time APIs, use
  // them, otherwise fall back to the Navigation Timing 1 API.
  if (window.PerformanceNavigationTiming && performance.timeOrigin) {
    const ntEntry = performance.getEntriesByType('navigation')[0];
    return (ntEntry.loadEventEnd + performance.timeOrigin) / 1000;
  } else {
    return performance.timing.loadEventEnd / 1000;
  }
}

firstPaintTime

function firstPaintTime() {
  if (window.PerformancePaintTiming) {
    const fpEntry = performance.getEntriesByType('paint')[0];
    return (fpEntry.startTime + performance.timeOrigin) / 1000;
  }
}

firstPaintAfterLoadTime

function firstPaintTimeAfterLoad() {
  // This was never actually implemented and always returns 0.
  return 0;
}
function navigationType() {
  if (window.PerformanceNavigationTiming) {
    const ntEntry = performance.getEntriesByType('navigation')[0];
    return ntEntry.type;
  }
}

wasFetchedViaSpdy

function wasFetchedViaSpdy() {
  // SPDY is deprecated in favor of HTTP/2, but this implementation returns
  // true for HTTP/2 or HTTP2+QUIC/39 as well.
  if (window.PerformanceNavigationTiming) {
    const ntEntry = performance.getEntriesByType('navigation')[0];
    return ['h2', 'hq'].includes(ntEntry.nextHopProtocol);
  }
}

wasNpnNegotiated

function wasNpnNegotiated() {
  // NPN is deprecated in favor of ALPN, but this implementation returns true
  // for HTTP/2 or HTTP2+QUIC/39 requests negotiated via ALPN.
  if (window.PerformanceNavigationTiming) {
    const ntEntry = performance.getEntriesByType('navigation')[0];
    return ['h2', 'hq'].includes(ntEntry.nextHopProtocol);
  }
}

npnNegotiatedProtocol

function npnNegotiatedProtocol() {
  // NPN is deprecated in favor of ALPN, but this implementation returns the
  // HTTP/2 or HTTP2+QUIC/39 requests negotiated via ALPN.
  if (window.PerformanceNavigationTiming) {
    const ntEntry = performance.getEntriesByType('navigation')[0];
    return ['h2', 'hq'].includes(ntEntry.nextHopProtocol) ?
        ntEntry.nextHopProtocol : 'unknown';
  }
}

wasAlternateProtocolAvailable

function wasAlternateProtocolAvailable() {
  // The Alternate-Protocol header is deprecated in favor of Alt-Svc
  // (https://www.mnot.net/blog/2016/03/09/alt-svc), so technically this
  // should always return false.
  return false;
}

connectionInfo

function connectionInfo() {
  if (window.PerformanceNavigationTiming) {
    const ntEntry = performance.getEntriesByType('navigation')[0];
    return ntEntry.nextHopProtocol;
  }
}

移除计划

chrome.loadTimes() API 将在 Chrome 64 中弃用, 已于 2018 年底移除。开发者应尽快迁移其代码 以避免数据丢失

打算弃用 | Chromestatus Tracker | Chromium bug