En aras de mejorar los tiempos de respuesta y la experiencia del usuario en una página web, constantemente tratamos de mejorar los algoritmos que usamos en el servidor, aunque la excusa sea una simple micro-optimización.
Sin embargo, generalmente descuidamos una parte muy importante: el front-end. Da la sensación de que en la parte cliente todo sirve: montones (a veces decenas) de recursos CSS y JavaScript “desparramados” por todas partes (en el header, footer ó simplemente en cualquier posición dentro del DOM), imágenes de tamaños desproporcionados redimensionadas por el navegador, recursos externos que tardan más de lo deseable en cargar, un código fuente de miles de líneas (con espacios y tabulaciones innecesarias)… Pero no nos paramos a pensar en cómo podemos mejorar.
En un proyecto tuvimos mejorar los tiempos de carga del front-end de una web, dado que los tiempos eran mejorables. Gracias a Chrome Developer Tools pudimos extraer las primeras conclusiones, para conocer el alcance del problema y los posibles puntos de mejora:
Aunque los tiempos del primer byte son buenos, la cantidad de requests y el tamaño total del documento no son para tirar cohetes. Cierto es también que el portal sirve vídeos, imágenes… Por lo que el tamaño del documento puede no ser del todo surrealista.
Revisando el layout, nos percatamos de una gran cantidad de recursos CSS servidos por separado; en total, 6 archivos. Además de ello, 7 scripts enlazando a archivos JavaScript estaban siendo cargados. Todo ello prácticamente en el inicio del documento.
TIP 1)
Usar algún tipo de “asset manager” (en nuestro caso Assetic), que nos permita combinar y minificar los recursos CSS y JS que cargamos. Con ello, reducimos de 6 a 1 los archivos CSS cargados, y de 7 a 1 los recursos JavaScript. Por tanto, ¡aligeramos en 11 peticiones la carga de la página!
No contentos con ello, aplicamos minificación y el resultado incluye también una reducción en el tamaño de los assets. Un paso final podría ser mover los scripts al final de la página, aunque no resultaba sencillo, dado que algunas páginas dependían de dichos recursos, lo que provocaría errores en el parseo del JavaScript. Pero no está de más el consejo: siempre que sea posible, mover los recursos JavaScript al final del documento.
A pesar de las mejoras aplicadas, el renderizado sigue siendo algo lento. Con la ayuda de la herramienta WebPageTest, comprobamos que la raíz del problema son los banners publicitarios. Los recursos JavaScript requieren bastante más tiempo del deseado en cargarse por completo. Y posterior al proceso de carga, se inicia el proceso de scripting y “dibujado” (renderizado) en la pantalla. El proceso es costoso, y supone un problema debido a que dependemos en gran medida de que el servidor externo funcione correctamente.
TIP 2)
Movemos los scripts al final de la página para evitar bloqueos, y mediante JavaScript, recolocamos los bloques en cuanto el documento esté completamente cargado. Con ello ganamos unas décimas nada despreciables.
La página hace uso de plugins sociales como Facebook Comments, Twitter Timeline y Google Analytics, cargados de forma síncrona.
TIP 3)
Una mejora para evitar “page blocking” es la carga de scripts de forma asíncrona.
Un ejemplo podría ser el código de tracking de GA:
Al resto de recursos JavaScript cargados desde un servidor externo le agregamos el atributo “async” de HTML5. Para entender el funcionamiento del atributo, podéis consultar aquí: Load Non-Blocking JavaScript with HTML5 Async and Defer.
TIP 4)
Reducir el tamaño del HTML resultante: El documento resultante son más de 2300 líneas, por lo que decidimos también comprimir el resultado. Aunque el contenido se envía Gzipped, nunca está de más reducir el tamaño del documento resultante. El proyecto emplea el framework Symfony2, así que la tarea es tan simple como añadir un listener al evento kernel.response, y comprimir el resultado con una simple expresión regular. ¿El resultado? De 114 kB a 75 kB.
TIP 5)
Reducción del tamaño de las imágenes: El documento tiene un tamaño de casi 4 mB (demasiado, sí), por lo que ordenamos por tamaño los recursos, y nos damos cuenta de lo evidente: de los 10 recursos más pesados, 5 son imágenes. Son 913 kB de información (¡prácticamente una cuarta parte de la web!).
Usamos una librería de manipulación de imágenes para eliminar meta-información de las mismas, y reducimos la calidad de las mismas (prácticamente inapreciable al ojo humano). Nuevamente los resultados son muy positivos: reducimos de media en un 65% el tamaño de las imágenes, dejando la tasa de transferencia 1 mB por debajo de los 3,9 iniciales (sin incluir las mejoras comentadas en el TIP1).
Para finalizar, os mostramos la situación actual según Chrome Developer Tools :D :