Contenido

3+1 formas de comprimir nuestro CSS desde PHP

22 dic

+ 13

Una forma de conseguir que nuestras páginas parezcan que cargan más rápido es usar la comprensión Gzip para devolver los ficheros CSS/JS comprimidos y así aligerar el peso de los mismos. Para ello podemos hacerlo de 3 formas diferentes:

Llamada HTML al fichero comprimido:

<link rel="stylesheet" type="text/css" media="screen" href="/style.css.php"/>

Al tratarse de un sistema basado en PHP, simplemente tendremos que llamar al fichero .php que se encargará de comprimirnos la salida de nuestro CSS.

Test de velocidad

Vamos a provechar y testear cada uno de los métodos a ver que tal se comporta con un fichero CSS de diferentes tamaños:

  1. 21kb
  2. 105kb
  3. 2mb

Para evitar cacheos, he añadido un rand() como parámetro al nombre del fichero. En las imagenes colocadas despues de cada método veremos los resultados de los diferentes pesos de ficheros y en cada uno de ellos nos encontraremos 3 líneas de tiempo en las que veremos a uno.css y css.php que son los ficheros que nos importan para este post.

  • uno.css, el fichero CSS plano con los estilos en los diferentes pesos.
  • css.php, los métodos encargados de comprimir el fichero uno.css.

Ambos devuelven el mismo CSS, uno.css en formato plano y css.php comprimido.

1) El método Paul Stamatiou

<?php if(extension_loaded('zlib')){ob_start('ob_gzhandler');} header("Content-type: text/css"); ?>
...
[CSS File]
...
<?php if(extension_loaded('zlib')){ob_end_flush();}?>

Insertamos el contenido CSS de nuestra hoja de estilos en lugar de [CSS File].

URL del método

Test de velocidad realizado

Fichero CSS de 21kb

paul-stamatiou-2

Fichero CSS de 105kb

paul-stamatiou

Fichero CSS de 2mb

paul-stamatiou-3

2) El método Perishable Press

<?php
   ob_start ("ob_gzhandler");
   header ("content-type: text/css; charset: UTF-8");
   header ("cache-control: must-revalidate");
   $offset = 60 * 60;
   $expire = "expires: " . gmdate ("D, d M Y H:i:s", time() + $offset) . " GMT";
   header ($expire);
?>

Insertaremos este código al inicio de nuestro fichero CSS, podemos modificar el tiempo de expiración del fichero ampliando así el cacheo del mismo.

URL del método

Test de velocidad realizado

Fichero CSS de 21kb

perishable-press-2

Fichero CSS de 105kb

perishable-press

Fichero CSS de 2mb

perishable-press-3

3) El método Reinhold Weber

<?php
  header('Content-type: text/css');
  ob_start("compress");
  function compress($buffer) {
    /* remove comments */
    $buffer = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $buffer);
    /* remove tabs, spaces, newlines, etc. */
    $buffer = str_replace(array("\r\n", "\r", "\n", "\t", '  ', '    ', '    '), '', $buffer);
    return $buffer;
  }

  /* Sus ficheros CSS */
  include('ficheros1.css');
  ...
  include('ficherosN.css');

  ob_end_flush();
?>

Simplemente tendremos que importar mediante include() los ficheros CSS que deseemos comprimir y automáticamente obtendremos un único fichero CSS comprimido para nuestra aplicación.

URL del método

Test de velocidad realizado

Fichero CSS de 21kb

reinhold-weber-2

Fichero CSS de 105kb

reinhold-weber

Fichero CSS de 2mb

reinhold-weber-3

4) El método aNieto2k

<?php
  // Directorio de estilos
  $dir = 'styles/';

  header('Content-type: text/css');
  ob_start("compress");

  function compress($buffer) {
    $buffer = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $buffer);
    $buffer = str_replace(array("\r\n", "\r", "\n", "\t", '  ', '    ', '    '), '', $buffer);
    return $buffer;
  }

  	/* Sus ficheros CSS */
	if ($gestor = opendir($dir)) {
    	while (false !== ($archivo = readdir($gestor))) {
			if (eregi(".css$",$archivo)) {
				include($dir.$archivo);
			}
    	}
    closedir($gestor);
	}
  ob_end_flush();
?>

Personalmente, me gusta el sistema propuesto por Reinhold Weber (aunque es el más lento), pero se me ha ocurrido que podría ser interesante modificarlo para que podamos coger todos los ficheros .css de un directorio y comprimirlos en uno solo. De esta forma no tendremos que modificar el fichero cada vez que añadieramos una hoja de estilos nueva.

Conclusiones

No hace falta ser un experto para darse cuenta que los métodos 1 y 2 ofrecen un mejor resultado en cuanto a compresión y tiempo de respuesta y es que el include() se nota. En el método 3, el exceso peso de los ficheros CSS es debido a que este mantiene la estructura de saltos de línea del fichero original frente a los métodos 1 y 2 que dejan el fichero CSS en una sola línea.

A la hora de elegir un sistema u otro, es interesante tener en cuenta las posibilidades de todos los métodos y sopesar los costes de tiempo y peso de cada uno de ellos.

  • Sí señor, que hoy con las velocidades que alcanzan las conexiones ya parece que casi nadie se preocupa por optimizar el peso de una web.
    Gran idea :)

  • Hace tiempos hice un “csszip” http://donestandares.wordpress.com/2008/09/25/comprime-tus-css-de-100-bajalos-a-27/ este es mas sencillo funciona con modrewrite y gzip, es sencillo y es codigo abierto!.

  • ¿El método Paul Stamatiou, serviría también para archivos javascript??

    He estado haciendo pruebas, y parece que si (cambiando, por supuesto el text/css del Content-type por application/x-javascript).

    Sin embargo, hay algo que me mosquea en los datos que tira el firebug…

    Para el css, la cabecera contiene estos datos:
    Content-Encoding gzip
    Vary Accept-Encoding
    Content-Length 1371
    Keep-Alive timeout=15, max=98
    Connection Keep-Alive
    Content-Type text/css

    Y el javascript:
    Content-Encoding gzip
    Vary Accept-Encoding
    Keep-Alive timeout=15, max=97
    Connection Keep-Alive
    Transfer-Encoding chunked
    Content-Type application/x-javascript

    Ese transfer-encoding: chunked es producto de la compresión, ok… pero, ¿puede llegar a influir en algo? Es más… porque al css no se le aplica esta codificación para la transferencia y al js si??

    Un saludo :)

  • En el trabajo hemos realizado una aproximación similar, pero que tiene la ventaja que nos deja el CSS comprimido en producción (sin necesidad de ejecutar el script de compresión a cada petición) y nos permite trabajar en el entorno de desarrollo con los distintos archivos CSS (y sin necesidad de editar el HTML).

    Desde el HTML llamamos a un solo archivo CSS, llamado main.css. Este contiene varios @import que cargan los distintos archivos CSS. Esto funciona perfectamente en el entrono de desarrollo y nos permite mantener separados los distintos CSS.

    Para subir a producción, ejecutamos un script PHP que lee el main.css, coge cada uno de los archivos CSS allí referenciados, los comprime, los concatena y los guarda en el propio main.css. De esta forma tenemos el CSS comprimido en un único archivo y no necesitamos editar nada en el HTML para que todo siga funcionando correctamente.

    Para el tema del caching usamos el .htaccess donde le definimos un tiempo de expiración muy largo para los archivos CSS. Pero cuando el CSS es modificado nos interesa que el navegador se lo vuelva a descargar. Para conseguirlo basta con añadir el timestamp de modificación del archivo main.css en la URL: href=”main.css?v=1228209925″

    Este mismo mecanismo se puede usar también para los archivos JS (en nuestro caso usando JSMIN para comprimirlos).

    Un saludo!

Comentar

#

Me reservo el derecho de eliminar y/o modificar los comentarios que contengan lenguaje inapropiado, spam u otras conductas no apropiadas en una comunidad civilizada. Si tu comentario no aparece, puede ser que akismet lo haya capturado, cada día lo reviso y lo coloco en su lugar. Siento las molestias.