¿En qué podemos ayudarte?
La cache del navegador es muy importante para mejorar la velocidad de carga de una web y proporcionar una buena experiencia de navegación a nuestros visitantes. Pero si no la gestionamos adecuadamente, podemos encontrarnos con que los usuarios acceden a una versión antigua y los resultados serán diametralmente opuestos a los deseados.
Veamos que podemos hacer para que nuestros vistantes accedan en todo momento a la última versión disponible
Como funciona la cache del navegador
La cache del navegador funciona de una manera muy simple. El navegador mantiene una copia local de los archivos descargados y antes de cada solicitud el se comprueba si el recurso solicitado ya ha sido descargado. Si ese es el caso se utiliza la copia local y nos ahorramos la descarga.
En realidad, este mecanismo es la base de todos los sistemas de cache. Se almacenan los resultados de cada petición para reutlilizarlos posteriormente cuando sea necesario.
A pesar de su utilidad, a veces la cache nos juega alguna que otra mala pasada, y algún cambio reciente es ignorado. En esos casos es necesario recargar la página de manera forzada o incluso vaciar completamente la cache. En este enlace, están las instrucciones para la mayoría de los navegadores.
Mecanismos de gestión de cache
Como desarrolladores, tenemos cierto control sobre la cache del navegador mediante algunas directivas en nuestro servidor. Básicamente indicamos al navegador el tiempo que debe mantener las copias en el almacenamiento local. La recomendación es ampliar todo lo posibe el plazo para archivos estáticos que no se modifican casi nunca, por ejemplo imágenes, hojas de estilo css y scripts
Eso de no modificar nunca, no es cierto si estamos en fase de desarrollo. Tampoco lo es cuando implementamos una funcionalidad nueva o solucionamos una incidencia. En esos casos necesitamos que los cambios sean visibles de inmediato.
Veamos como hacerlo
Mediante cabeceras HTML
Es un muy sencillo deshabiltar la cache para ciertas partes del contenido, solo debemos incorporar el siguiente código al HEAD de las páginas afectadadas
<meta http-equiv="Expires" content="0">
<meta http-equiv="Last-Modified" content="0">
<meta http-equiv="Cache-Control" content="no-cache, mustrevalidate">
<meta http-equiv="Pragma" content="no-cache">
Si generamos nuestro contenido mediante PHP, entonces usaremos las instrucciones
header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
header("Expires: Sat, 1 Jan 1900 05:00:00 GMT"); // Indicamos una fecha en el pasado
Esto obliga al navegador y proxyies intermedios a limpiar la cache existente y volver a cargar las páginas afectadas desde el servidor.
Esta solución debe ser considerarada como algo temporal y pasado un tiempo prudencial debemos eliminar las directivas para continuar aprovechando las ventajas de usar cache.
Uso de cabeceras ETAGs
Invalidar la cache de página tiene la desventaja que siempre se carga toda la página, aunque solo hayamos modificado un archivo. Imaginemos una página con videos, imágenes, etc. El tiempo de carga aumentará significativamente y todos sabemos lo que eso significa.
Para intentar solucionar este problema, se implementó dentro del protocolo HTTP el uso de cabeceras ETAG (Etiquetas de Entidad). En este caso, el servidor asigna a cada archivo o recurso un identificador único, que permite al navegador saber cuales han sido modificados, De esta forma se cargan solo los que hayan sido modificados desde el último acceso.
Su funcionamiento también es simple. Con la primera descarga de un recurso, el navegador recibe el ETAG correspondiente. A partir de ese momento hace una peticion indicando el ETAG correspondiente y si el servidor responde que no ha cambiado se usa la copia local.
Este método tiene dos inconvenientes;
- Requiere una petición adicional por cada recurso solicitado
- Tenemos que ocuparnos de todos los detalles de implementación del protocolo, entre ellas la generacion de ETAS y las cabeceras de respuesta enviadas por el servidor. Algunos servidores como es el caso del Apache nos ayudan a configurarla para los elementos estáticos
Versionado de recursos para controlar la cache del navegador
Hay una forma relativamente sencilla de controlar los archivos almacenados en la cache del navegador. Como ya dijimos, si el navegador cree se trata de otro archivo lo descargará directamente y en caso contrario usará la copia local. No habrá peticiones adicionales.
Para lograrlo convertiremos nuestros recursos estaticos en peticiones dinámicas parametrizadas. Un ejemplo de petición de este tipo puede ser una búsqueda: https://tienda.rjcardenas.com/?s=msi&product_cat=pcs-integracion&post_type=product
Dependiendo de los parámetros (el contenido de la url a partir de la ?) obtendremos resultados diferentes. Por tanto su modificación hará que la copia local sea ignorada y el navegador se descargue el archivo modificado. Por ejemplo, si utilizamos la sintaxis:
<link rel="stylesheet" src="//dominio.com/assets/css/style.css?v=2922" >
será suficiente modificar el valor 2922 para forzar la descarga de style.css.
Si usamos PHP, podemos automatizar el proceso, utilizando fa función filemtime(), la cual nos devuelve la fecha de modificacion del archivo
<link rel="stylesheet" src="//dominio.com/assets/css/style.css?<?php echo filemtime('ruta-hacia-style.css'); ?>" >
Usando este método, podemos trabajar tranquilamente con style.css, confiando en que los visitantes verán la versión actualizada. Cada vez que guardemos nuestro trabajo, la versión se actualizará automáticamente.
Esta solución es válida para cualquier otro tipo de archivo, solo tenemos que adaptarla a nuestro caso concreto.
Implementación en WordPress
El caso más frecuente es la modificación de hojas de estilo y scripts. WordPress nos ofrece funciones específicas para gestionarlos:
Para los CSS => wp_enqueue_style (identificador, origen, dependencias, version, tipo-de-medio)
Para los scripts => wp_enqueue_script (identificador, origen, dependencias, version, en-el-footer)
Donde:
- identificador - es nuestro nombre interno para el recurso
- origen - la URL de acceso al recurso
- dependencias - una matriz donde indicaremos los recurso de los que depende, Util si queremos establecer un orden de carga
- versión - nuestro identificador único para el recurso
- tipo-de-medio - en los css cuando querems que se utilice
- en-el-footer - si queremos que el script se cargue al final de la página
Podríamos implementar la carga en el functions.php de nuestro tema-hijo con un código similar a
function rjc_carga_forzada() {
$fs=get_stylesheet_directory();
$url=get_stylesheet_directory_uri()
$css_file='style.css';
$js_file='archivo.js';
wp_enqueue_script('rjc_js', $url .'/'.$js_file, array('jquery'), filemtime($fs.'/'.$js_file), true);
wp_enqueue_style('rjc_css', $url .'/'.$css_file, array(), filemtime($fs.'/'.$css_file), 'screen');
}
add_action('wp_enqueue_scripts', 'rjc_carga_forzada');
Y ya podemos trabajar tranquilamente en nuestro sitio.
Conclusiones
Hemos visto como automatizar el versionado nuestros recursos estáticos. Esto nos permitirá aprovechar las ventajas de la cache del navegador, y nuestros usuarios siempre verán la versión correcta de nuestros contenidos. Es un método simple y efectivo que uso habitualmente en mis desarrollos y que según mi experiencia no interfiere con otras técnicas de cache.
Los ejemplos mostrados nos dan una idea para incorporar este método a nuestros proyectos. Tendremos todas las ventajas de las ETAGs, sin necesidad de configuraciones especiales.
¿Usas alguna otra técnica para llevar a cabo esta tarea? Cuéntanos tu experiencia.