Speedy js: 2. Navigation Timing

Introducción al api Navigation Timing y la optimización de la descarga y renderización de un sitio web

Fernand Léger

archivado en: JavaScript / 26 octubre, 2015 / taller:

En la entrada anterior de esta serie dedicada a la optimización del desarrollo web conocimos performance.now(), una herramienta muy interesante para calcular cuánto tiempo se demora un proceso javaScript a partir de su medición mediante High Resolution Time, que es una especie de timestamp con una precisión extraordinaria. En esta veremos otra api similar, Navigation Timing, sobre la acaba de publicarse un segundo borrador de la w3c en el momento de escribir estas líneas. Como aún no está implementada esta versión, aquí hablaré de la primera. Pero antes aviso que resultará más comprensible si conocemos el protocolo http aunque sea por encima. De no ser así, recomiendo la lectura de esta otra entrada.

Performance.timing

Desde que solicitamos al navegador que nos muestre el contenido de una web -por ejemplo escribiendo su dirección, pulsando un enlace o refrescando una página- hasta que se muestra por pantalla con sus estilos css y su código js, suceden una montón de procesos que deben estar optimizados para que el usuario vea algo en el menor tiempo posible. Según Google, lo ideal sería que ocurrieran en menos de un segundo. Aunque creo que es un margen demasiado bajo para una página sofisticada, es una meta a la que vale la pena intentar llegar y para eso nos puede resultar de gran ayuda el api de Navigation Timing.

La lógica de su funcionamiento es similar a la que vimos para performance.now(). Mediante la interfaz PerformanceTiming, se calcula el lapso de tiempo transcurrido entre dos eventos o hitos predefinidos y ese es el tiempo que ha tardado en ejecutarse un proceso ([final] - [comienzo] = [tiempo de ejecución]). Algo así para aclararnos:

  1. Evento 1: por ejemplo, se intenta conectar con un servidor y justo ese momento se guarda, en tiempo UNIX timestamp, en la propiedad "conexionServidorEmpieza" de performance.timing.
  2. Evento 2: se establece la conexión del servidor y se vuelve a medir el timestamp, un valor que se guarda en la propiedad "conexionServidorTermina".
  3. La diferencia entre el Evento 2 y el Evento 1 son los milisegundos que ha demorado el proceso de establecer la conexión con el servidor.

En código. Dado que en la propiedad fetchStart queda definido el momento en que el navegador empieza a solicitar cosas a un servidor si no las tiene cacheadas; y que en domComplete se guarda el momento en que el dom ha terminado de cargarse, la diferencia entre los dos hitos será el tiempo en que ha tardado en cargarse la página por primera vez.

/* Recogemos el análisis cuando la página ha terminado de cargarse */

window.addEventListener("load", function() {

setTimeout(function() {

var calculo = window.performance.timing;

var tiempoCarga = calculo.domComplete - calculo.fetchStart;

console.log("La página ha tardado en cargarse " + tiempoCarga + " milisegundos");

}, 0);

}, false);

Disponemos de herramientas muy cómodas para analizar la información que nos pueda aportar performance.timing, como las que tenemos en la propia consola del chrome, que veremos más adelante; sin embargo, creo que es interesante analizar con cierto detalle el tema para ir conociendo cuáles son los hitos críticos del proceso y cómo tratarlos para que se resuelvan de la forma más rápida posible.

Estos procesos a los que me he estado refiriendo se pueden agrupar en dos grandes conjuntos:

  1. las cosas que suceden antes de que se empiece a procesar una página, como una redirección,
  2. y las que pasan durante el renderizado de la página.

Para entender esta clasificación podemos pensar en una panadería: primero hay que reunir todos los ingredientes (la sal, la harina, la levadura...) y una vez que están todos en el local, en el cliente, se puede empezar a preparar el pan, la página.

hitos de PerformanceTiming  en una ilustración de la w3c

hitos de PerformanceTiming en una ilustración de la w3c

 

A. Reuniendo los ingredientes

  1. navigationStart: Es el primer evento que se lanza, lo primero que sucede cuando se intenta acceder a una url. Si el recurso que se solicita no está cacheado equivale a fetchStart.
  2. unloadEventStart / unloadEventEnd: Si dos documentos, uno que se está abandonando y otro que se está solicitando, tienen el mismo origen, el tiempo que tarda en descartarse por completo el primero. En otra situación, el valor es cero.
  3. redirectStart / redirectEnd: el tiempo en que comienza y termina una redirección http. Si no hay ninguna, el valor retornado es 0.
  4. fetchStart: el momento en que el navegador, el cliente, está listo para solicitar un documento al servidor antes de comprobar si existe o no en la caché.
  5. domainLookupStartdomainLookupEnd: El principio y el final para la resolución del DNS.
  6. connectStartconnectEnd: El tiempo en que empieza y acaba de establecerse la conexión con el servidor (TCP).
  7. secureConnectionStart: Lo mismo, pero para la conexión segura.
  8. requestStart: el momento en que el navegador envía la solicitud de un recurso (request), ya sea al servidor o a la caché.
  9. responseStartresponseEnd: desde que se recibe el primer byte de la respuesta (response), al último, ya sea desde el servidor o la caché.

Hasta aquí todos los procesos están relacionados con el intercambio inicial de información entre el cliente y el servidor; vamos ahora con el trabajo final que debe realizar el navegador una vez que ha reunido todos los ingredientes.

B. Preparando el pan

  1. domLoading: el momento en que el navegador comienza a procesar un documento html, sin tener en cuenta ni las css ni el js ni cualquier otro tipo de recurso adicional. Es decir, solo el código html.
  2. domInteractive: cuando ha terminado de digerir el documento html (sin más recursos). Es decir, cuando el DOM está construido por completo.
  3. domContentLoadedEventStart domContentLoadedEventEnd: cuando empieza y termina la ejecución del javaScript.
  4. domComplete: cuando ha terminado por completo todo el proceso relacionado con el DOM, el javaScript y las CSS incluidos. (Equivale al estado "complete" de readyState).
  5. loadEventStartloadEventEnd: cuando empieza y termina de lanzarse el evento load(), que es el evento de jQuery $(document).ready(), para aclararnos.

Todo junto en una imagen:

timing

 

Herramientas gráficas

El api de Navigation Timing, por lo tanto, es una herramienta muy útil para analizar los momentos críticos de la descarga y renderización de una página web, pero lo más chulo es que hay herramientas gráficas que nos permiten recabar esa información de manera muy cómoda. Como me da cierta pereza explicar pantallas, me limito a enumerar un par de ellas.

1. El Timeline de la consola del Chrome. Probablemente sea la más potente, aunque quizás por eso resulte la más compleja de manejar hasta que no se tengan muy claros algunos conceptos. Aquí se explica en detalle.

timeline_chrome

2. La herramienta red (net) del firebug de Firefox, que es la que recomiendo cuando se está empezando por su mayor claridad. Aquí se puede descargar.

timeline_firefox

Bueno, pues ahora que ya sabemos cómo medir la carga de una página, podemos pasar a ver cómo optimizar el proceso, pero será ya en la próxima entrada de esta serie, que por hoy está bien.

|| Tags: ,

valoración de los lectores sobre Speedy js: 2. Navigation Timing

  • estrellica valoración positiva
  • estrellica valoración positiva
  • estrellica valoración positiva
  • estrellica valoración positiva
  • estrellica valoración positiva
  • 5 sobre 5 (1 votos)

¿Te ha parecido útil o interesante esta entrada?
dormido, valoración 1 nadapensativo, valoración 2 un poco sonrisa, valoración 3 a medias guiño, valoración 4 bastante aplauso, valoración 5 mucho

Tú opinión es muy importante, gracias por compartirla!

Aportar un comentario


*