LO QUE VAMOS A VER

Qué controlan las cabeceras HTTP, cómo versionar tus archivos en WordPress y qué comprobar cuando el navegador sigue mostrando una versión antigua.

Publicas un cambio en el CSS o en un script y algunos visitantes siguen viendo la versión anterior. Vaciar tu navegador puede servir para diagnosticarlo, pero no es una solución que puedas exigir a tus clientes. La publicación debe permitir identificar la nueva versión del recurso.

En esta guía separaremos las directivas HTTP, la validación de una copia y el versionado de las URL. Después veremos un ejemplo de WordPress que utiliza la fecha de modificación de los archivos locales, con sus límites y las comprobaciones necesarias antes de dar por resuelto un problema de caché.

Cómo funciona la caché del navegador

El navegador puede reutilizar una respuesta que tiene almacenada mientras su política de caché lo permita. No necesita preguntar al servidor por cada archivo en cada visita. Cuando debe validarla, puede hacer una petición condicional para comprobar si sigue siendo válida.

En una web intervienen más capas: la caché de páginas del servidor, una CDN o un service worker pueden participar en la respuesta. La configuración de una capa no garantiza el comportamiento de las demás. Ante un archivo antiguo, primero hay que identificar de dónde procede.

Una respuesta HTML, una hoja de estilo y un archivo JavaScript son recursos distintos. Cambiar la política del HTML no cambia automáticamente las cabeceras de los otros archivos ni elimina todas sus copias almacenadas.

Directivas HTTP y validación

Cabeceras de respuesta: almacenar y reutilizar

La política se comunica mediante cabeceras HTTP de la respuesta. Las directivas tienen propósitos diferentes:

DirectivaSignificado
max-age=3600Define un plazo de frescura de una hora, sujeto a las demás reglas aplicables.
no-cachePuede almacenar la respuesta, pero debe validarla antes de reutilizarla.
no-storeIndica que no se almacene esa respuesta.
privateImpide almacenarla en una caché compartida; permite una caché privada.

Por tanto, no-cache no significa «no guardar». Tampoco una cabecera enviada ahora vacía globalmente las cachés de todos los recursos. Las reglas de HTML personalizado y las de archivos públicos deben definirse según el contenido que se sirve.

Las etiquetas <meta http-equiv="Cache-Control"> del ejemplo antiguo no son un mecanismo fiable para imponer esta política HTTP y no configuran las respuestas de CSS o JavaScript. Revisa las cabeceras reales que envía el servidor o la CDN. Esta revisión no modifica su configuración.

ETag y Last-Modified: validar una copia

Un ETag es un validador que el servidor puede proporcionar para una representación. Cuando corresponde validarla, el cliente puede enviarlo en If-None-Match. Si sigue siendo válida, una respuesta 304 Not Modified permite reutilizar la copia sin volver a transferir su cuerpo.

Last-Modified y If-Modified-Since ofrecen otro mecanismo de validación basado en fechas. No hay que confundir estas comprobaciones con pedir siempre otra descarga: una respuesta todavía fresca puede reutilizarse sin esa validación.

El versionado de URL y los validadores cumplen funciones diferentes y pueden convivir. Añadir una versión no reproduce «todas las ventajas de ETag» ni configura por sí solo las cabeceras del recurso.

Versionar CSS y JavaScript en WordPress

Una versión permite que el HTML apunte a una URL diferente cuando publicas un cambio. En un enlace de hoja de estilo el atributo correcto es href, no src:

Código
<link rel="stylesheet" href="/assets/css/site.css?ver=1700000000">
<link rel="stylesheet" href="/assets/css/site.css?ver=1700000200">

El ejemplo muestra dos publicaciones, no dos enlaces que debas cargar a la vez. Para aprovecharlo, el navegador debe recibir el HTML que referencia la versión nueva. Si una caché de página sigue sirviendo el enlace anterior, cambiar el archivo no resolverá por sí solo lo que ve ese visitante. Una CDN también debe tener en cuenta el parámetro de versión en su clave de caché.

Ejemplo con archivos locales y filemtime()

En WordPress utilizamos wp_enqueue_style() y wp_enqueue_script(). Su parámetro $ver acepta una cadena que WordPress añade como versión a la URL. Pasar false usa la versión de WordPress; pasar null omite el parámetro. Aquí proporcionaremos una versión propia para cada archivo.

filemtime() obtiene la fecha de modificación de un archivo del sistema de archivos. Necesita una ruta local, no la URL del navegador. La siguiente función devuelve una versión estable de publicación si el archivo no está disponible o no se puede consultar:

Código
function rjc_version_recurso(string $ruta, string $version_publicacion): string
{
    if (!is_file($ruta) || !is_readable($ruta)) {
        return $version_publicacion;
    }

    // The file could disappear between the check and stat during a deployment.
    $marca = @filemtime($ruta);
    return false === $marca ? $version_publicacion : 'mtime-' . $marca;
}

La supresión de aviso se limita a filemtime(), por si el archivo desaparece durante un despliegue entre la comprobación y la consulta. No genera una versión aleatoria ni usa la hora de cada petición, lo que inutilizaría la reutilización entre visitas.

Este ejemplo está pensado para los archivos assets/css/site.css y assets/js/site.js de un tema. Las funciones get_theme_file_path() y get_theme_file_uri() buscan primero en el tema hijo y después en el padre; usamos el mismo nombre relativo para obtener ruta y URL:

Código
function rjc_cargar_recursos_versionados(): void
{
    $version_publicacion = '2026.11.09';
    $css = 'assets/css/site.css';
    $js  = 'assets/js/site.js';

    $ruta_css = get_theme_file_path($css);
    if (is_file($ruta_css) && is_readable($ruta_css)) {
        wp_enqueue_style(
            'rjc-site',
            get_theme_file_uri($css),
            [],
            rjc_version_recurso($ruta_css, $version_publicacion)
        );
    }

    $ruta_js = get_theme_file_path($js);
    if (is_file($ruta_js) && is_readable($ruta_js)) {
        wp_enqueue_script(
            'rjc-site',
            get_theme_file_uri($js),
            [],
            rjc_version_recurso($ruta_js, $version_publicacion),
            true
        );
    }
}
add_action('wp_enqueue_scripts', 'rjc_cargar_recursos_versionados');

Coloca ambas funciones en el tema hijo y adapta los nombres y rutas a los archivos que realmente utilizas. No carga los archivos ausentes. El identificador rjc-site debe ser propio: intentar registrar otra vez un identificador que ya utiliza otro código no sobrescribe automáticamente sus datos.

Las dependencias están vacías porque este ejemplo no presupone ninguna. Si tu script necesita jQuery u otro recurso registrado, decláralo en su array. El último true coloca el JavaScript en el pie; no activa por sí solo async ni defer. Para recursos de un plugin utiliza sus rutas y URL correspondientes; no apliques filemtime() directamente a una biblioteca externa.

Límites del método y despliegues

La fecha de modificación no es una huella del contenido. Un despliegue que conserva timestamps, o dos cambios dentro de la resolución de esa fecha, pueden mantener la misma versión. En esos entornos conviene utilizar una versión de publicación o nombres generados a partir del contenido, como site.a81f3c.css.

Para recursos cuyo contenido no cambia durante su plazo de frescura se puede utilizar immutable. Un nombre con hash ayuda a cumplir ese contrato: al cambiar el contenido se publica otro nombre y se conservan los archivos que todavía referencian páginas antiguas. No apliques esa promesa indiscriminadamente a una URL cuyo contenido vas a sustituir.

Coordina la publicación de los archivos, el HTML y las purgas necesarias en la CDN o caché de páginas. Si usas un service worker, revisa también sus reglas. Versionar el CSS no vacía esas otras capas ni garantiza que todas las personas reciban inmediatamente el HTML nuevo.

Comprobar el resultado

  • Abre la pestaña Red de las herramientas del navegador y localiza el recurso. Comprueba su URL completa y la versión, no solo el nombre del archivo.
  • Revisa la respuesta y sus cabeceras: Cache-Control, validadores y, si procede, indicadores de la CDN como Age. Comprueba el contenido que efectivamente has recibido.
  • Modifica el archivo, publícalo y verifica que el HTML referencia otra versión. Confirma también que no se sigue sirviendo una página antigua desde otra capa.
  • Haz una prueba con la caché del navegador habilitada. Desactivarla en las herramientas o forzar una recarga puede ayudar a diagnosticar, pero no demuestra el comportamiento de un visitante normal.

Conclusiones

Versionar recursos es una forma práctica de publicar cambios sin pedir a cada visitante que limpie su navegador. Funciona junto con una política HTTP apropiada y una publicación coherente del HTML, los archivos y las capas intermedias.

El ejemplo de WordPress se ha comprobado con archivos temporales y las funciones reales de registro y carga: versiones independientes, cambio de fecha, archivo ausente y URL generada. También se comprueba expresamente el límite de cambiar el contenido sin cambiar su timestamp.

Esas pruebas validan el código y las etiquetas generadas; no certifican las cabeceras de tu servidor ni la clave de caché de una CDN. Esas comprobaciones deben hacerse sobre el entorno en el que publicas.

Referencias

CONVERSAMOS SOBRE LA GUÍA

¿Tienes alguna pregunta?

Deja tu comentario

Tu correo no se publicará. Revisamos los comentarios antes de publicarlos. No incluyas información privada.

Utilizaremos los datos para gestionar la conversación y protegerla frente al spam. Consulta la política de privacidad.