Archivo de etiquetas de 'optimización'

Optimizar la carga de una web (y IV)

Una entrada aún más rápida para comentar el resultado del siguiente paso de la optimización, que ha sido Minificar (que poco me gusta este palabro) el código Javascript y los CSS. Para comprimir estos ficheros he usado YUI Compressor, que es un programa Java hecho por el mismo grupo de Yahoo! mismo que hace posible YSlow.

Gracias a esta herramienta hemos reducido el tamaño de los ficheros a descargar en 30Kb, y por tanto arañamos unos milisegundos al tiempo total, sobretodo con la caché vacía que era el apartado que menos había mejorado (e incluso empeorado durante un paso). YSlow nos da un aprobado alto con una puntuación de 90, ya queda poco para terminar el trabajo.

Optimizar la carga de una web (y III)

Esta actualización es mucho más rápida ya que he tenido la suerte de tener mucho trabajo hecho. Los dos siguientes pasos que nos indicaba YSlow, añadir la cabecera Expires y comprimir el contenido, ya los teníamos bastante avanzados gracias al paso anterior. Pero aún quedaban algunos elementos de la página que no cumplían esta regla, básicamente todos lo que no pude mover a la CDN.

Para solucionar el problema rápidamente he modificado el fichero ‘gzip-header-css.php’ que venía incluido en el tema K2 que uso, y lo he dejado así:

gzip-header.php
  1. <?php
  2.         // Browser check. props phpBB
  3.         $browser = ( !empty( $_SERVER['HTTP_USER_AGENT'] ) ) ? strtolower( htmlspecialchars( ( string ) $_SERVER['HTTP_USER_AGENT'] ) ) : '';
  4.  
  5.         // check to see if the user has enabled gzip compression in the WordPress admin panel
  6.         if( ( $browser and strpos( $browser, 'msie 6.0') === false) and extension_loaded( 'zlib' ) and !ini_get( 'zlib.output_compression' ) and ini_get( 'output_handler' ) != 'ob_gzhandler' and ( ( version_compare( phpversion(), '5.0', '>=') and ob_get_length() == false) or ob_get_length() === false ) ) {
  7.                 ob_start( 'ob_gzhandler' );
  8.         }
  9.  
  10.         // The headers below tell the browser to cache the file and also tell the browser it is JavaScript.
  11.         header( "Cache-Control: public" );
  12.         header( "Pragma: cache" );
  13.  
  14.         $ExpStr = "Expires: " . gmdate( "D, d M Y H:i:s", strtotime( '+1 year' ) ) . " GMT";
  15.         $LmStr = "Last-Modified: " . gmdate( "D, d M Y H:i:s", filemtime( $_SERVER['SCRIPT_FILENAME'] ) ) . " GMT";
  16.  
  17.         header( $ExpStr );
  18.         header( $LmStr );
  19. ?>

Lo que he hecho ha sido quitar la parte que indicaba el Content-Type, para poder indicar CSS y JS en función de lo que vaya a necesitar, y cambiar la forma de calcular la fecha de Expires para usar un método más intuitivo.

Añadiendo el include de este fichero a las tres peticiones que faltaban, conseguimos una A en estos dos test y una puntuación de 88 en el total, que ya empieza a estar bastante bien. La media del tiempo de carga con la caché vacía ha subido casi un segundo quedándose en unos 7 segundos, pero la media usando la caché ha bajado casi un segundo hasta llegar a los 3 segundos. De momento no hemos mejorado apenas, pero quedan dos puntos que nos pueden ayudar bastante: minificar el código Javascript y pasar la carga de los ficheros .js al final del documento.

Optimizar la carga de una web (y II)

Para continuar optimizando la carga del blog, el siguiente paso que nos recomiendan desde Yahoo! es usar una Content Delivery Network (CDN) que reparta la entrega de los datos estáticos (imágenes, CSS y JS principalmente) usando una red de servidores repartidos por todo el mundo.

Normalmente el uso de estas redes está reservado para grandes corporaciones que pueden pagarlas, pero nosotros vamos a apoyarnos en la infraestructura de Google para descargar a nuestro pobre servidor de atender estas peticiones, y de paso permitir que el navegador descargue en paralelo los ficheros, ya que al estar en dominios distintos no estará limitado por el número máximo de descargas simultaneas.

Lo primero que vamos a hacer es usar el API de Google para cargar las librerías Javascript que usa el blog. En este apunte encontraréis una explicación detallada de las ventajas de usar este API. Si usamos wordpress, este plugin nos hará todo el trabajo sucio.

Después tenemos que añadir a la configuración de YSlow el dominio ‘ajax.googleapis.com‘ para que nos reconozca lo que descarga desde esa dirección como perteneciente a nuestra CDN. El como hacerlo lo podemos ver en su FAQ.

El siguiente paso es pasar todo el contenido estático a otra CDN. Para ello vamos a hacer un poco de trampa y usar el servicio de Google App Engine para montarnos una CDN. Con la información de esta entrada monté lo básico y pasé todo lo que pude a la página de Google Apps, pero me mosqueaba que siempre se recargaban las imágenes, los css y los js, y con Firebug vi que Google no respondía a las peticiones If-Modified-Since y siempre devolvía el contenido como nuevo. Al fichero de la aplicación hay que añadirle la linea ‘default_expiration: “365d”‘ para que la fecha de expiración se de en un año por defecto.

En esta otra entrada continúan el trabajo de la anterior pero añadiendo el control de la cache del navegador y así evitar enviar los datos con cada petición.Como en el anterior apartado, deberemos añadir el dominio que creemos a la configuración de YSlow para que nos lo tenga en cuenta.

Después de este cambio los tiempos de carga no han variado apenas, pero hemos descargado bastante nuestro servidor principal, con lo que en caso de necesitar atender a muchas peticiones lo tendrá más fácil. Además, los servidores de Google comprimen de forma automática los ficheros de texto (css y js) por lo que ahorramos en ancho de banda.

La puntuación que nos da YSlow ha subido hasta 80, no sólo por usar la CDN sino porque al utilizarla hemos mejorado otros puntos como añadir la cabecera de Expires, comprimir el contenido o configurar los ETags (estos no son compatibles con las CDNs por lo que todo lo que se descarga de una no necesita tener esa cabecera).

Optimizar la carga de una web

La página principal de este blog tarda en cargar entre 5 y 6 segundos con la caché vacía y entre 3 y 4 segundos una vez cacheada, dependiendo de lo ocupado que esté el servidor. Un tiempo bastante alto, que vamos a intentar mejorar.

Para ayudarnos vamos a utilizar YSlow, un plugin para FireBug (si, un plugin para un plugin). Este plugin comprueba si se cumplen las reglas que diseñaron en el grupo de Exceptional Performance de Yahoo!

Si le indicamos que analice la portada del blog, nos da una puntuación (usando el sistema anglosajón) de F (34), un suspenso como un camión.

La primera regla en la que suspendemos (con una F) es en la de realizar pocas peticiones HTTP, ya que para cargar la página hacen falta 10 ficheros JS, 6 CSS y 28 imágenes. De los 10 JS, 6 pertenecen al tema de wordpress que uso y los otros 4 a plugins. Intentar unificar los ficheros de distintos plugins sería una locura, pero los que pertenecen al tema vamos a reunirlos en 1 para reducir casi a la mitad el número total.

Después vamos a usar la técnica de Sprites CSS (vía el generador automático) para unificar todas las imágenes que usan tanto el tema K2/Vader como el plugin de Compártelo, para pasar de 28 imágenes descargadas a 6. Como beneficio añadido tenemos que podemos optimizar los PNGs y pasar de 20,7Kb en imágenes a 6,9Kb. lo cual nunca viene mal.

Ya que no resultaba muy complicada también eliminamos la llamada a un css cuya única función era cargar la el css principal en php.

Tras todos estos pasos, hemos reducido las peticiones a 6 JS, 5 CSS y 6 imágenes. Ahora obtenemos una C en este apartado e incrementamos la puntuación total en 14 puntos. Para obtener un sobresaliente en esta apartado tendríamos que reescribir partes fundamentales de Wordpress, del Tema y los plugins.

Por ejemplo, se me ocurre que el motor de Wordpress podría tener un par de funciones con las que los plugins y temas puedan indicarle que ficheros JavaScript y CSS quieren usar respectivamente, y este los uniera en uno solo para enviárselo al navegador. De esta forma tendríamos siempre una sola petición JS y otra CSS independientemente de cuantos plugins tuviéramos instalados. Estos envíos podrían estar comprimidos y su compresión sería mayor que la de cada uno de los elementos por separado.

Actualización: A sugerencia de mi amigo Juan, voy a ir poniendo los tiempos que se ganan con cada modificación para poder ver como afectan al tiempo total cada uno de ellos. Pero también tengo que decir que los tiempos en si mismos son bastante difíciles de medir, ya que el blog está en un servidor en el que también hay un juego online, y la carga que este impone al servidor hace variar mucho los tiempos. Por eso voy a intentar medir el tiempo desde el mismo sitio y a las mismas horas para intentar que los parámetros de la medición sean lo más parecidos posibles.

Los resultados son un poco raros, ya que el tiempo de carga con la caché vacía ha aumentado en casi 1 segundo (probablemente debido a que ahora en la portada se cargan imágenes más grandes debido a los Sprites CSS); pero una vez los datos están en caché el tiempo medio ha bajado en casi medio segundo. Habrá que esperar a tener más resultados para comparar.




Cerrar
Enviar por Correo