O Chrome 64 vai suspender o uso da API chrome.loadTimes()

chrome.loadTimes() é uma API não padrão que expõe métricas de carregamento e informações de rede aos desenvolvedores para ajudá-los a entender melhor o desempenho do site no mundo real.

Desde que essa API foi implementada em 2009, todas as informações úteis que ela informa podem ser encontradas em APIs padronizadas, como:

Essas APIs padronizadas estão sendo implementadas por vários fornecedores de navegadores. Como resultado, o chrome.loadTimes() está sendo descontinuado no Chrome 64.

A API descontinuada

A função chrome.loadTimes() retorna um único objeto que contém todas as informações de carregamento e rede. Por exemplo, o objeto a seguir é o resultado da chamada de chrome.loadTimes() em www.google.com:

{
  "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"
}

Substituições padronizadas

Agora é possível encontrar cada um dos valores acima usando APIs padronizadas. A tabela a seguir corresponde cada valor à API padronizada, e as seções abaixo mostram exemplos de código de como receber cada valor na API antiga com equivalentes modernos.

chrome.loadTimes() recurso Substituição de API padronizada
requestTime Tempo de navegação 2
startLoadTime Tempo de navegação 2
commitLoadTime Tempo de navegação 2
finishDocumentLoadTime Tempo de navegação 2
finishLoadTime Tempo de navegação 2
firstPaintTime Marcação de tempo
firstPaintAfterLoadTime N/A
navigationType Tempo de navegação 2
wasFetchedViaSpdy Tempo de navegação 2
wasNpnNegotiated Tempo de navegação 2
npnNegotiatedProtocol Tempo de navegação 2
wasAlternateProtocolAvailable N/A
connectionInfo Tempo de navegação 2

Os exemplos de código abaixo retornam valores equivalentes aos retornados por chrome.loadTimes(). No entanto, para novos códigos, esses exemplos não são recomendados. O motivo é que chrome.loadTimes() fornece valores de tempo no tempo de época em segundos, enquanto as novas APIs de desempenho geralmente informam valores em milissegundos em relação à origem de tempo de uma página, que tende a ser mais útil para a análise de desempenho.

Vários dos exemplos também favorecem as APIs Performance Timeline 2 (por exemplo, performance.getEntriesByType()), mas oferecem substitutos para a API Navigation Timing 1 mais antiga, que tem suporte mais amplo a navegadores. A partir de agora, as APIs Performance Timeline são preferenciais e geralmente são informadas com maior precisão.

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;
  }
}

Plano de remoção

A API chrome.loadTimes() será descontinuada no Chrome 64 e será removida no final de 2018. Os desenvolvedores precisam migrar o código o mais rápido possível para evitar perda de dados.

Intenção de descontinuação | Rastreador do Chromestatus | Bug do Chromium