Mejorando la velocidad de las tiendas nube

Fede Iglesias
Tiendanube Design
Published in
8 min readFeb 25, 2019

En Tiendanube hacemos mucho foco en lo que es la experiencia de compra, puliendo día a día flujos de UX pero sin perder el detalle en la UI, que es lo que le da personalidad a cada plantilla que tenemos.

Pero además de esto una de las claves para lograr una gran experiencia es la velocidad de nuestras plantillas, por eso decidimos trabajar en llevarla al siguiente nivel y en este artículo voy a contarte los detalles de lo que hicimos para lograrlo.

En lo que tardaste en leer esta primera oración hasta acá, aproximadamente la mitad de tus usuarios abandonaron tu sitio. Un 53% de los usuarios abandonan un sitio si ese no carga antes de los 3s. Sí, así de importante es la velocidad.

De nada sirve tener un sitio pixel perfect o con funcionalidades que el usuario necesita, si tarda tanto en cargar que genera frustración y abandono antes de llegar a ver algo.

¿Dónde estábamos parados?

A la hora de entender cómo estábamos en relación a la velocidad de carga, teníamos que saber que tipo de tiendas teníamos:

  • Tiendas de muestra: Dónde tenemos control absoluto de lo que se muestra y el contenido subido (imágenes, Javascript, CSS).
  • Tiendas de clientes reales: Dónde seguimos teniendo control pero un poco más limitado ya que a veces los clientes pueden agregar plugins o scripts de JS externos desde el administrador de su tienda que pueden impactar la velocidad .
  • Tiendas reales con un diseño a medida: Acá el control es bastante reducido ya que se suma el caso de una tienda real y la posibilidad de que los archivos base de cada plantilla sean modificados por un diseñador/desarrollador externo.

Considerando solo el primer tipo de tiendas, las de muestra, demoraban mucho en cargar obteniendo un resultado de aproximadamente 46 puntos de performance midiendo con herramientas como PageSpeed y Lighthouse.

Si no teníamos control sobre estas tiendas, menos íbamos a tener sobre el resto.

Los resultados hechos en la tienda Simple con PageSpeed
Resultados medidos con Lighthouse para la misma tienda

Para entender un poco más sobre como medir esto pueden ver este artículo:

¿Qué hicimos?

Conociendo el problema, y en base a los resultados de las pruebas hechas, pudimos ver tres frentes donde accionar.

Las imágenes

Fueron el caso más claro donde estábamos fallando:

  • Cargando imágenes grandes sin optimizarlas en base a cada dispositivo o el componente que la muestra (grilla de productos, banner, etc)
  • Cargando todas las imágenes apenas comenzaba a verse el sitio
  • Dejando un espacio en blanco hasta que las imágenes eran cargadas por el navegador, dando mala experiencia de cómo se percibe la carga.

Esto impactaba mucho en la velocidad y la experiencia ya que podíamos tener imágenes que pesaban megas o simplemente estábamos cargando 50 imágenes de productos que el usuario no necesitaba ver apenas carga el sitio.

Implementando el atributo SRCSET de HTML pudimos obtener las imágenes con el tamaño adecuado a la pantalla de cada dispositivo, evitando llamar una imagen de 1080px en un teléfono donde podíamos llamar una de 480px.

Por otro lado aplicamos la técnica de lazy load (a través del plugin lazysizes) para obtener solo las primeras imágenes que se ven apenas carga el sitio, e ir llamando al resto a medida que el usuario hace scroll en la pantalla.

A través del lazy load pudimos mostrar un “spinner” (el ícono que gira indicando la carga de la imagen) para la grilla y banners; así como un placeholder tipo “wireframe” para el slider principal y de producto.

De esta forma pudimos mejorar la experiencia de lo que se mostraba hasta obtener la imagen final, pero no estábamos conformes ya que, si bien mejoramos la percepción de mostrar que algo se estaba cargando, no estábamos adelantando mucha información sobre que es lo que iba a aparecer luego y es clave poder adelantar lo más que podamos para mejorar la percepción de velocidad (además de la velocidad obviamente) mientras el resto del sitio se sigue cargando.

Fue por eso que decidimos pulir un poco más e implementar la técnica de LQIP (Low Quality Image Placeholders). En lugar de mostrar un icono girando, cargamos la imagen en un tamaño muy chico con un efecto blur (para que no se viera pixelada) hasta que lazy load muestre la imagen final y de esta forma el usuario puede previsualizar mejor el contenido que va a cargarse.

Por último trabajamos en reemplazar todos los íconos de Font Awesome visibles apenas carga el sitio (por ejemplo en la navegación) por su versión en SVG.

Este es un formato gráfico hecho por vectores que cargan más rápido en lugar de esperar a que el navegador “pinte” pixel por pixel toda la imagen.

Para detalles de como implementamos esto paso a paso, les dejo este artículo donde pueden ver exactamente lo que hicimos en el código:

El JavaScript

Además de las imágenes, el JavaScript es algo que afecta bastante a la velocidad, bloqueando la carga del HTML que pueda encontrase debajo del propio script (en términos del DOM). Esto hace que el navegador no muestre nada de lo que le sigue al JS hasta que éste no haya cargado por completo, bloqueando por ejemplo lo que hay en el body (si el JS es cargado en el head).

El Javascript es un Hodor que impide que el contenido pase por la puerta.

Para mejorar esto atacamos:

  • Como estábamos cargando el Javascript
  • La cantidad de plugins que teníamos en las tiendas
  • Los widgets de redes sociales

En nuestras tiendas usamos Jquery y si bien es una librería que ahorra mucho trabajo, también pesa bastante. Para reducir el impacto de esto comenzamos a cargarla de forma asincrónica, haciendo que el navegador lo cargue cuando lo disponga sin bloquear nada. Esto también fue aplicado a todos los scripts donde podíamos hacerlo sin romper las funcionalidades (obviamente).

Por otro lado teníamos muchos plugins que resolvían nuestros problemas a corto plazo pero estábamos generando mucha deuda técnica que impactaba en la carga. Para reducir esto limpiamos plugins que ya estaban obsoletos o podían ser reemplazados con poco JavaScript hecho por nosotros e incluso solo CSS.

Además de esto separamos los plugins que quedaban en dos, los que cargábamos de forma asincrónica (por ejemplo plugins que dependen de Jquery como bxSlider o el JS de Bootstrap) y los que necesitábamos que carguen lo antes posible (por ejemplo lazyload).

Por último haciendo pruebas de velocidad nos dimos cuenta que los widgets de la Facebook page y o el feed de Twitter, ¡Disminuían la performance en hasta 20 puntos!

Si pueden removerlos mucho mejor, de lo contrario piensen alguna forma de reemplazarlo por algo donde tengan todo el control del componente (CSS, JS e imágenes).

Si les interesa entender en profundidad como fue el paso a paso de los cambios de JS les recomiendo ver:

El CSS

Si bien dejamos el CSS último en este artículo, no significa que sea el menos importante ya que bloquea la vista del sitio igual que lo hace el JavaScript, solo que en este caso no podemos cargarlo todo como async, porque estaríamos mostrando HTML sin estilos (es decir roto) hasta que el navegador los cargue.

Por esto fue que decidimos partir el CSS en tres:

  • CSS crítico: Es el más importante (por ejemplo para la nav o el logo) y lo cargamos inline dentro del tag <style> de HTML en el <head> del sitio para garantizar que el contenido más importante se vea estilado en los primeros segundos de carga. Este CSS debe ser lo más corto posible.
  • CSS no crítico: Es el menos importante y puede ser cargado asincrónico, por ejemplo el footer.
  • CSS de configuraciones: Este debemos obtenerlo de la forma clásica, bloqueando el contenido ya que está relacionado a configuraciones de color y tipografías que necesitamos cargar antes del HTML.

Para ver en detalle los cambios de CSS que trabajamos vean:

Conclusión

Aplicando estos cambios logramos llevar nuestras tiendas de muestra a un 93 con PageSpeed y 87 con Lighthouse.

Resultados hechos con PageSpeed
Resultados hechos con Lighthouse

Siempre recordar que las imágenes son una gran parte de la velocidad de carga, luego el JS y por último (no menos importante) el CSS.

¿Y las tiendas que no son de muestra? Buena pregunta, en estás tiendas llevamos la performance de la mayoría de 20/30 pts a 70/75pts con los mismo cambios. Si bien es un cambio importante, todavía estamos trabajando en mejorarlo.

¿Fin? ¡Para nada!

Todavía seguimos trabajando en pulir cada vez más la velocidad de las tiendas. Mirando cada detalle, cada script externo que pueda estar afectando, cada imagen que pueda ser cargada innecesariamente o no tenga el tamaño ideal.

Algo tan importante como hacer estos cambios es mantenerlos, no te olvides de preguntarte con cada cambio que hagas ¿Cómo afecta la velocidad esto que estoy haciendo?

Gracias por tomarte este rato e interesarte en mejorar la velocidad de carga de sus sitios, espero que te haya servido y haber aportado un granito de arena a mejorar la experiencia en sus sitios.

¡Gracias también a Bruno Navello y Seba Marcó! Product designers que la rompen en Tiendanube y trabajaron conmigo en mejorar la velocidad.

[Actualización 09/2020]

Este artículo muestra mejoras de performance previas a la actualización de Google Lighthouse 6 durante Mayo del 2020. Si bien siguen vigentes, hubo nuevos aprendizajes que podés ver este otro artículo. 👇

--

--