Versionado de archivos CSS y Java Script: Un método para forzar la renovación de la caché
«Sé porqué estás aquí. Sé lo que estás haciendo. […] Es la pregunta, la que nos impulsa, Neo. Es la pregunta la que te ha traído aquí. Conoces la pregunta igual que yo…» ¿Qué son las extensiones que hay tras los archivos .css y .js y que tanto abundan últimamente? ¿Por qué cuando trabajo con WordPress esas malditas extensiones me impiden actualizar el CSS de la web?
Pues bien, cogiendo el guante de Trinity en su conversación con Neo, diremos que la respuesta estaba ahí, frente a tus ojos, ha estado siempre ahí: Eso, son las llamadas versiones de archivo, y sirven para forzar la renovación de la caché.
En este artículo vamos a explicarte cómo se usan y porqué es un método tan popular últimamente a pesar de que, como comentamos en el artículo sobre «¿Qué es la caché y porqué no se muestran los cambios que realizo?«, existen otros métodos para forzar la renovación continua de la caché de navegador.
¿Qué es y para qué se usa el versionado de archivos?
Sabemos lo importantísimo que resulta la velocidad de carga en una página web, tanto de cara a la paciencia del usuario, como de cara al uso de datos en conexiones móviles.
Tanto es así que desde Loopeando.com no nos cansamos de repetir que cada segundo de más que tarda en cargar tu web, es público que pierdes. Por no mencionar que la velocidad de carga es uno de los factores del posicionamiento web.
Por todo ello, tanto servidores como navegadores, tienen distintos sistemas para almacenar determinados datos en la llamada caché web. El objetivo de ésto no es otro que evitar que al acceder a una página debamos cargar continuamente los mismos datos, si estos no van a cambiar. Y ese es el problema, que hay determinados datos que sí son cambiantes y… si el navegador o el servidor evita que se renueven, los cambios que hagamos no se mostrarán al usuario final.
Precisamente por ello se empiezan a usar las versiones. Una versión no es otra cosa que una pequeña extensión que añadimos al final de un archivo sobre el que realizamos cambios frecuentes o que se modifica dinámicamente.
Por ejemplo:
Si yo tengo un archivo de css, pongamos general.css, cuando realicemos una modificación de alguno de los estilos, dicho cambio no tiene porqué mostrarse de inmediato, ni en nuestro ordenador, ni en el de los clientes. El que se muestre antes o después dependerá de la configuración de las diversas cachés (caché de servidor y de los navegadores individuales de cada usuario).
Pero yo puedo «engañar» a los sistemas de caché haciéndoles creer que ese archivo de css es en realidad otro archivo totalmente nuevo. ¿Cómo? Con una extensión de texto, una variable GET, una versión.
Mi archivo orginal:
<link href="css/general.css" rel="stylesheet">
Mismo archivo al que le hemos añadido una versión:
<link href="css/general.css?v=1" rel="stylesheet">
Con esto consigo 2 cosas:
- Como decíamos, que el archivo no se vea condicionado a la caché y los cambios que vayamos realizando se muestren de inmediato.
- Que todo aquel código que haga uso de dicho archivo siga funcionando correctamente puesto que el nombre del mismo no ha cambiado.
Y en efecto, si en lugar de llamar al archivo general.css fuésemos cambiándolo de nombre cada vez (general2.css, general3.css, general4.css…), conseguiríamos el mismo resultado, pero el trabajado que supondría tener que estar cambiando todas las referencias a él de la web sería inmenso.
Versiones dinámicas: Diferentes scripts para crearlas
Y ahora la gran pregunta, ¿Cómo agrego una versión a un archivo? ¿Escribo ese texto tal cual en el nombre ? Es una posibilidad, pero desde luego, poco práctica.
Si vamos a estar realizando modificaciones con cierta frecuencia, o el CSS y el JS dependen de un formulario que el usuario pueda editar a su antojo, lo ideal es que utilicemos variables globales para cambiar todos los archivos de una vez.
Ejemplos:
<link href="css/general.css?v=${version}" rel="stylesheet"> <link href="css/estilos.css?v=${version}" rel="stylesheet"> <script type="text/javascript" src="/js/codigo.js?v=${version}"></script>
De esta forma, si aplicamos la variable «version» a los archivos que se editen con frecuencia o estén sujetos a edición dinámica, tras cada cambio se renovarán todos.
¿Y qué valor asigno cada vez? Eso ya es imaginación de cada uno. Hay tantas maneras como personas: Podemos hacer variables incrementales, o asignar la fecha, o un número aleatorio…
Aquí algunos ejemplos:
Con variables aleatorias en PHP:
<link rel="stylesheet" href="css/visual.css?v=<?php echo(rand()); ?>" /> <script src="js/visual.js?v=<?php echo(rand()); ?>"></script>
Con variables aleatorias en Java Script:
<script type="text/javascript"> var estilos = 'js/visual.js?' + Math.random(); </script>
Con fecha y hora exacta de la modificación:
<script type="text/javascript" src="visual.js?v=<?php echo time();?>"> </script>
Con .htaccess:
<?php function autoVer($url) { $path = pathinfo($url); $ver = '.'.filemtime($_SERVER['DOCUMENT_ROOT'].$url).'.'; return $path['dirname'].'/'.str_replace('.', $ver, $path['basename']); } ?> <link rel="stylesheet" href="<?php echo autoVer('/private/css/visual.css'); ?>" /> <script src="<?php echo autoVer('/private/js/visual.js'); ?>"></script> #Regla para el .htaccess RewriteRule ^(private/(js|css|imgs)/)(.+)\.(.+)\.(js|css|jpg|gif|png)$ $1$3.$5 [L]
¿Y si deseo realizar una modificación pero no he creado yo el sistema de versiones?
Caso habitual: Necesito editar un CSS de WordPress. Localizo la línea donde se encuentra y la hoja de estilos, voy al archivo, lo edito ¡y voilà!… no pasa absolutamente nada. Limpio la caché de la web, la del navegador y… sigue sin pasar nada.
¿Qué está ocurriendo? Que yo estoy editando una hoja llamada, por ejemplo, general.css, pero la que se muestra en la web es general.css?v2.3.
¿Y dónde está general.css?v2.3? No está, no existe. Como decíamos, es una versión virtual generada sobre una hoja de estilo real. No puedo acceder a esa versión y por ende, no puedo hacer que esos cambios se muestren en la web.
¿No puedo? ¡Claro que puedes! Pero no a la vieja usanza.
En un CMS tipo WordPress
Lo ideal es que utilices la opción que traen casi todos los temas para editar el CSS. Esta opción es la que genera los CSS dinámicos, por lo que los cambios que realices ahí sí tendrán efecto.
Habitualmente está en Apariencia –> Personalizar CSS o en Apariencia –> Tema –> Personalizar CSS
Si no hay manera de editar por esa vía, tienes 2 opciones:
- Recurres a los plugins, por ejemplo WP Add Custom CSS
- Rompes la generación de versiones
Para esto último hay varios métodos. O bien vamos al functions.php del tema y ponemos el siguiente código:
// Remove the version number from Javascript & CSS files that are // enqueued using either `wp_enqueue_script()` or `wp_enqueue_style()` function microdot_remove_scripts_styles_version( $src ) { if ( strpos( $src, 'ver=' ) ) $src = remove_query_arg( 'ver', $src ); return $src; } // Remove the version from enqueued stylesheets (CSS) add_filter( 'style_loader_src', 'microdot_remove_scripts_styles_version', 9999 ); // Remove the version from enqueued javascript files add_filter( 'script_loader_src', 'microdot_remove_scripts_styles_version', 9999 );
O bien buscamos esta función y ponemos el 4to argumento ($ver) en false:
wp_enqueue_style( string $handle, string $src = false, array $deps = array(), string|bool|null $ver = false, string $media = 'all' );
O bien creamos otro archivo CSS clonando el que queríamos modificar, y lo subimos con la siguiente función:
wp_enqueue_style('Nombre_del_Tema', get_stylesheet_directory_uri() . '/style-ver-2.css');
En otro tipo de webs
Podemos o bien clonar el archivo CSS y cambiarlo de nombre para que esté fuera del flujo de versiones, o bien dar con el formulario que sí permite agregar esos cambios a las nuevas versiones del CSS, o bien editar las llamadas a CSS con alguno de los scripts que comentábamos en el punto «Versiones dinámicas: Diferentes scripts para crearlas».
O incluso usar algo como esto:
<link rel="stylesheet" href="style.css?nocache=" type="text/css" media="screen" />
¿Y tú, has tenido encontronazos con las versiones de CSS y JS? ¡Cuéntanos tu experiencia! y si lo conseguiste solucionar, cómo lo hiciste.
Escribir comentario