Performance e latência são alguns dos requisitos de qualidade e experiência do usuário mais desafiadores em desenvolvimento web, especialmente quanto à performance client-side.Sabemos como aplicar técnicas que melhoram muito a performance da página, mas medir o desempenho adequadamente já não é tão trivial à nossa rotina de desenvolvimento. Pensando nisso, o W3C tem uma nova recomendação chamada Navigation Timing API. Com isso, é possível obter métricas e estatísticas detalhadas de modo nativo sobre tempo de carregamento, navegação entre páginas e carregamento de eventos.
A vantagem desta API sobre ferramentas externas e outras técnicas de aferição de latência via JavaScript é a quantidade de informações que podem ser obtidas sobre o tempo de carregamento da página em diferentes fases, proporcionando a medição em um escopo maior (end-to-end). Ferramentas como o PageSpeed e o WebPageTest já têm utilizado dados da Navigation Timing API na análise de carregamento de páginas.
Suporte
Até o momento da escrita deste artigo, a Navigation Timing é suportada pelo Chrome 24.0+, Firefox 18.0+ e IE 9+. A especificação já é recomendação do W3C desde dezembro de 2012 e a versão 2 da API já está em desenvolvimento.
Utilizando o objeto window.performance
Os parâmetros de carregamento da página são acessados através das propriedades navigation e timing do objeto [window.]performance. A propriedade navigation contém informações sobre como o usuário chegou à página e a propriedade timing apresenta as informações sobre carregamento da página.
É possível testar o window.performance diretamente no console do navegador. Supondo que estamos utilizando o Chrome, basta abrir a Developer Tools > Console e digitar performance no prompt. Abaixo, um exemplo do que você poderá obter. Note que o Chrome adiciona mais uma propriedade chamada memory, que pode ser acessada pelo performance.memory, apresentando informações sobre a utilização de memória pelo JavaScript.
Cada uma destas propriedades do timing expressa o tempo de um determinado evento em milisegundos a partir das 00:00 do dia 1º de Janeiro de 1970 (UTC). Quando o valor de algum dos atributos é zero, significa que este evento não ocorreu.
Os tipos de navegação ou “como cheguei até esta página?”
A window.performance.navigation armazena dois atributos que pode ser utilizados para detectar como o usuário chegou à página atual, por exemplo, via um redirecionamento, botões de navegação do histórico do navegador ou entrada normal por URL na barra de endereço. Os atributos são:
- redirectCount****: o número de redirecionamentos que ocorreram até que a página final fosse carregada;
- type****: a forma como o usuário chegou à página.
O atributo type é uma constante do tipo enumerada e pode apresentar os seguintes valores:
Valor
Descrição
Navegação iniciada por click em um link, entrada de URL na barra de endereço do navegador, submissão de formulário ou por uma operação de script.
1
Recarregamento de página (por botão de refresh ou location.reload()).
2
Navegação através dos botões de avançar/voltar do navegador ou por operações de navegação no histórico através de script (ex.: history.back()).
255
Qualquer tipo de navegação que não se enquadre nos valores acima.
Os atributos de tempo de carregamento
A propriedade window.performance.timing armazena os dados relevantes sobre o tempo de carregamento desde o momento em que o navegador dispara a requisição para obter a página até o momento em que o carregamento de todo o documento é finalizado. A tabela abaixo mostra uma breve descrição destes eventos na ordem em que eles ocorrem:
Atributo
Descrição
navigationStart
Tempo depois de o documento anterior ter iniciado o evento de unload.
Tempo imediatamente antes do evento de unload ser disparado.
Tempo após o documento anterior ter completado o unload, ou seja, ter sido descarregado para que o próximo documento seja carregado.
Tempo da busca que iniciou o redirecionamento.
Tempo após a ocorrência do último redirecionamento.
Tempo em que o recurso começa a ser buscado.
Tempo imediatamente antes de iniciar a resolução de nome do domínio.
Tempo após finalizar a resolução de nome do domínio.
Tempo imediatamente antes de iniciar a conexão com o servidor para solicitar o recurso.
Tempo em que a conexão com o servidor é finalizada.
Para os browsers onde este atributo existe (o IE não o possui no momento), ele retorna o tempo em que foi iniciada uma conexão HTTPS.
requestStart
Tempo imediatamente antes da requisição do documento ao servidor.
Tempo imediatamente após o recebimento do primeiro byte de resposta do servidor.
Tempo após a finalização da resposta (recebimento do último byte) ou conexão com o servidor.
domLoading
Tempo em que o status do documento passa a ser “loading”.
Tempo em que o status do documento passa a ser “interactive” (DOM completamente interpretado pelo parser do user agent).
Tempo em que o evento DOMContentLoaded é disparado no documento.
Tempo após finalizar o evento DOMContentLoaded.
Tempo em que o status do documento passa a ser “complete”. O status “complete” difere do “interactive” pois engloba a execução de scripts.
Tempo em que inicia a execução do evento de load da página.
Tempo em que finaliza a execução do evento de load da página.
Conforme a developer Kasia explica em um artigo de seu blog, os eventos de Rede envolvem tudo que acontecem antes do browser enviar a requisição do documento e pode ajudar a medir latência de rede; os eventos de Servidor são referentes aos tempos de requisição e resposta do documento, ajudando a medir quanto tempo o servidor leva para processar a página; por fim, os eventos do Browser ocorrem a partir do momento que o documento é criado até o momento em que o evento de onload é disparado, auxiliando a medir de fato a performance client-side.
Na timeline abaixo, retirada da documentação da API, é possível ver o fluxo de execução destes eventos.****
Depois de toda esta fundamentação teórica, chegamos de fato no ponto que nos interessa, o pulo do gato: como utilizar estes dados para obter as métricas de performance. Geralmente, a forma de obter estas informações se dá pelo cálculo da diferença entre alguns atributos.
Compilando alguns exemplos apresentados pelo Sam Dutton do HTML5Rocks, Colin Ihrig do SitePoint e a documentação de JS da Mozilla, temos as seguintes combinações (mas é possível obter muito mais):
Cálculo
responseEnd – fetchStart
loadEventEnd – responseEnd
loadEventEnd – navigationStart
responseEnd – requestStart
redirectEnd – redirectStart
domainLookupEnd – domainLookupStart
connectEnd – connectStart
Acrescento também alguns testes que fiz com outros cálculos:
Cálculo
domInteractive – domLoading
domComplete – domLoading
loadEventEnd – loadEventStart
Exemplos
No site Web Timing Demo é possível ter uma prévia de como estes dados podem ser visualizados graficamente. Além disso, a aplicação mostra o valor de todas as propriedades da window.performance para aquela página.
Outra aplicação mais completa é o bookmarket desenvolvido pela Kasia, citada anteriormente neste artigo. Basta arrastá-lo para a barra de favoritos do browser e clicar nele em qualquer página que deseja analisar.
Referências e mais recursos
Can I Use… Navigation Timing API. Disponível em: https://caniuse.com/#feat=nav-timing
Colin Ihrig. Profiling Page Loads with the Navigation Timing API. Disponível em: https://www.sitepoint.com/profiling-page-loads-with-the-navigation-timing-api/
Internet Explorer Developer Center. Navigation timing (Windows). Disponível em: https://msdn.microsoft.com/en-us/library/ie/hh673552(v=vs.85).aspx
Kasia Drzyzga. Breaking Down OnLoad Event – Performance Bookmarklet. Disponível em: https://66.7percentangel.com/2011/12/breaking-down-onload-event-performance-bookmarklet/
Leigh Shevchik. It’s All in the Timing: How to Use the Navigation Timing Specification to Improve Web Performance. Disponível em: https://blog.newrelic.com/2012/05/16/its-all-in-the-timing-how-to-use-the-navigation-timing-specification-to-improve-web-performance/
Microsoft MSDN. performanceTiming object. Disponível em: https://msdn.microsoft.com/en-us/library/ff975075
Mozilla Developer Network. Navigation Timing. Disponível em: https://developer.mozilla.org/en-US/docs/Navigation_timing
Sam Dutton. Measuring Page Load Speed with Navigation Timing. Disponível em: https://www.html5rocks.com/en/tutorials/webperformance/basics/
W3C. HTML5: A vocabulary and associated APIs for HTML and XHTML. Disponível em: https://www.w3.org/TR/html5/syntax.html
W3C. Navigation Timing. Disponível em: https://www.w3.org/TR/navigation-timing/