Técnicas avanzadas para optimizar el rendimiento de carga de una web

Técnicas avanzadas para optimizar el rendimiento de carga de una página web

En este artículo se han agrupado un conjunto de buenas prácticas útiles para acelerar la velocidad de carga de las páginas de un sitio web. Estas técnicas sirven para mejorar el rendimiento de una página desde que el usuario hace la petición de una página hasta que se carga el último componente de la misma.

Todas ellas forman parte de un conjunto de normas que se pueden verificar y validar automáticamente a modo de tests con los plugins PageSpeed (de Google) y YSlow (de Yahoo), plugins instalables dentro del complemento Firebug del navegador Mozilla Firefox.

Aunque muchas de estas técnicas de optimización son aplicables a la mayoría de páginas web, es recomendable entender cuando hay que utilizarlas, pues hay casos y excepciones en que habrá que valorar si nos conviene. Por ello vale la pena conocerlas y usar las más complejas cuando se presenten verdaderos problemas de rendimiento.

Combinar archivos externos

Reducir el número de peticiones HTTP. Uno de los objetivos principales de optimización es reducir el número de peticiones que se hacen al servidor. Una página web no es sólo un documento HTML, también existen las cookies, las imágenes, archivos de estilo, archivos javascript y un largo etc.

Además, con la creciente popularidad del hosting en la nube (Cloud hosting) este es uno de los puntos más importantes a tener en cuenta, pues en estos servicios se paga por el número de peticiones que se hacen y por ello nos podrá interesar reducirlas al máximo.

Compactar documentos CSS y Javascript. Compactar cualquier tipo de código siempre aumentará la velocidad de descarga y mejorará el tiempo de ejecución. Eliminar información innecesaria como espacios, saltos de línea, etc. son bytes que aunque no lo parezca, en archivos grandes se nota la diferencia de tamaño.

Normalmente se intenta minimizar archivos estáticos, es decir, archivos que no se generan dinámicamente en cada petición y suelen mantener la información, como es el caso de archivos CSS y archivos Javascript.

Hay muchas herramientas online para minimizar estos códigos. Una de las más destacadas es la de Yahoo!, YUI Compressor que funciona por línea de comandos y permite minimizar Javascript y CSS.

También hay herramientas online como CSSDrive o Javascript Compressor.

En entornos de producción, es una buena idea ejecutar estas herramientas sobre el código una vez se vaya a hacer un deploy (subir la aplicación al servidor), en vez de compactar código dinámicamente.

Optimizar archivos de estilos CSS

Eliminar estilos CSS no usados Una vez terminado el diseño es necesario revisar los estilos CSS y eliminar cualquier código de las hojas de estilo que no se utilize. En sitios grandes cualquier byte que se ahorre puede suponer una gran diferencia.

Evitar utilizar instrucciones poco "ortodoxas" de CSS (ej: @import) Hay instrucciones que pueden y deben ser omitidas, @import es un ejemplo. Esta instrucción puede usarse dentro de un archivo CSS para importar otros archivos de estilo. Es una mala práctica ya que con cada nuevo archivo a descargar demoramos la carga total de la página. También es recomendable usar las instrucciones CSS más simples y estandar aceptadas por todos los navegadores.

Optimizar uso de imágenes

Las imágenes de un sitio web siempre son un lastre, pues ocupan bastante más espacio que el texto sin formato. Además cada imagen suele ser un archivo por separado lo que aumenta el número de peticiones.

Siempre que sea posible se deberán usar imágenes de tipo gif o png y evitar formatos jpeg, a menos que queramos mostrar fotografías de calidad.

Reducir el tamaño de las imágenes. Aun usando estos formatos, la mayoría de imágenes que forman parte de una web son imágenes de pocos colores, es por ello que es necesario utilizar herramientas de compresión y optimización de imágenes para ahorrarnos toda la información superflua que por error podemos haber añadido con nuestro editor gráfico. YSlow lleva integrado un optimizador de imágenes.

Mostrar imágenes a escala. Si una imagen tiene un tamaño específico no hay que reducirla usando HTML. Aunque en alguna ocasión pueda servir como atajo, en general es una mala práctica, pues una imagen mayor ocupa más espacio y por ende más peso en bytes. Es preferible tener varias copias de la misma imagen en distintos tamaños, por ejemplo si son imágenes subidas por los usuarios, guardar la imagen original, una versión de un tamaño normal y otra en miniatura.

Especificar tamaño de las imágenes. Definir el tamaño de las imágenes ayuda a renderizar más rápido a los navegadores, así no deben recalcular su tamaño al volver a pintar las imágenes.

Combinar imágenes en sprites CSS. Esta técnica consiste en analizar las imágenes que se usan más a menudo en todas las páginas de la web y juntarlas en un solo archivo, una al lado de otra. Luego usando instrucciones de CSS se puede hacer que sólo muestre una area determinada, que corresponderá a la imagen que queramos mostrar.

Crea un favicon de tamaño reducido y cacheable. El archivo favicon.ico es una imagen que permanece en la carpeta principal de acceso a la página web. Algunos navegadores realizan la petición del favicon en esa dirección automáticamente. Por ello se recomienda añadir un encabezamiento de expiración en el futuro y que ocupe menos de 1 Kb.

Aprovechar cache del navegador

Las webs cada vez se vuelven más complejas con tantos scripts, imágenes, hojas de estilo, etc. En la primera visita es cuando más peticiones HTTP se deberían responder para cargar todos los componentes en el navegador del cliente. En las visitas sucesivas del mismo usuario no deberían de volver a realizarse peticiones que ya se han ejecutado con anterioridad.

Por ello deberíamos cachear los elementos más comunes como las imágenes, pero también se deberían cachear scripts, archivos css y archivos flash principalmente.

Hay cuatro formas distintas de cachear contenido del lado del cliente:

HTTP Cache - Última modificación. Se trata de comprobar la fecha de la última modificación del archivo. En caso que no se haya modificado el archivo se envía un encabezamiento de respuesta indicándolo. Sin necesidad de descargar el archivo por completo.

Etags. Parecido al anterior pero mejor debido a que no se compara por fecha sino que se genera un hash con los bytes del archivo, haciéndolo único, de forma que si se modifica, la llave hash da otro valor, lo que significa que se ha modificao.

Expiración. Añadiendo a cada asset (recurso) una fecha de expiración en el futuro hace que si se vuelve a pedir el mismo archivo, si el navegador detecta que aun no ha expirado, ni siquiera se molesta en hacer otra petición al servidor y muestra el recurso cacheado desde el navegador.

Max-Age. Parecido al anterior, pero en vez de asignar una fecha en el futuro, se le asigna un tiempo máximo de vida. Una vez transcurrido, el recurso ya está listo para expirarse a la siguiente petición.

Habilitar compresión gzip

Comprimir los archivos que se envían desde el servidor hasta el cliente utilizando Gzip puede reducir el tamaño de los ficheros hasta un 75%. Si bien es cierto que se incrementa el uso de CPU en cada petición, seran contados los casos en que esto sea un problema. Tan sólo hay que ver que sitios que manejan una cantidad inmensa de datos como Facebook comprimen con gzip todos sus contenidos.

La forma más fácil de comprimir contenido es dejar que el mismo servidor lo haga. Apache tiene un mod llamado moddeflate que se encarga de comprimir los ficheros a gzip y enviar los _headers correspondientes. Basta decir que sólo se deben comprimir los documentos HTML, CSS y Javascript, pues las imágenes no se pueden comprimir más (ver apartado de optimizar imágenes).

Otras técnicas

Usar redes de distribución de contenido (CDN Content delivery network). Una red de distribución de contenido es una red de servidores distribuidos en diferentes puntos geográficos para enviar el contenido a los usuarios de una forma más eficiente. Esta red "inteligente" permite conectar un usuario con su servidor más cercano para reducir la latencia y enviar el contenido más rápido.

Estas redes son recomendables para sitios grandes y establecidos pues para startups o sitios pequeños puede suponer un gasto no asumible.

Evitar el uso de redireccionamientos Hay varias formas de redireccionar páginas, una de las más lentas es usar javascript. Ya que se debe descargar toda la página y posteriormente ejecutar el código. Otra forma es usando redireccionamientos mediante el envío de los encabezamientos de una petición HTTP de tipo 301 o 302.

Hay maneras incluso de evitar estos últimos redireccionamientos. Se trata de usar mod_rewrite para reescribir las rutas (si el contenido está en el mismo servidor), o incluso crear un record CNAME (una entrada DNS que crea un alias que apunta de un dominio a otro) junto con mod_rewrite si se trata de otro dominio. Estas redirecciones suelen usarse para migrar rutas de sitios antiguos.

Evitar peticiones erróneas. Las peticiones HTTP al servidor que devuelven el error 404 no encontrado deben ser evitadas a toda costa, pues a parte de causar gran daño a la experiencia del usuario, se usan recursos del servidor que podrían usarse para otras cosas.

La mejor forma de evitar estas peticiones es buscar en los logs del servidor para tratar de arreglar el problema y no se vuelvan a mostrar en el futuro.

Paralelizar las descargas en múltiples dominios En la especificación HTTP 1.1 se puede leer que los navegadores sólo deberían permitir como máximo dos conexiones concurrentes por nombre de host para descargar los contenidos de la web (documento HTML, imágenes, vídeos, etc).

Lógicamente, esto hace que los ficheros que no se están descargando queden en espera haciendo aumentar el tiempo total de descarga. Hay una manera de tratar este inconveniente: servir los recursos de múltiples dominios. De esta forma se "engaña" al navegador para hacerle creer que está descargando de distintos sitios, lo que aumenta el tiempo de carga de la página.

Para terminar...

La mayoría de estas normas han sido recopiladas, resumidas y reordenadas de la documentación y las guías de usuario de las aplicaciones PageSpeed y YSlow. Para obtener una información más extenda de cada una de ellas podéis acceder a YSlow guide o PageSpeed.

Google PageSpeed y Yahoo YSlow son quizá las herramientas más populares para observar y evaluar la carga y rendimiento de páginas web en el lado del cliente (lo que en inglés se conoce como Page Profiling). Pero hay muchísimas más, como por ejemplo: Cuzillion, Apache JMeter, UA Profiler, Hammerhead, Gomez/Keynote/WebMetrics/Pingdom and Jiffy/Episodes (estas últimas de uso comercial) entre otras que también sirven para realizar tests más especializados o para un rango mayor de páginas.