La caché del navegador permite reutilizar una respuesta HTTP en lugar de descargar nuevamente el mismo recurso. Utiliza plazos largos para archivos públicos cuya URL cambia al cambiar su contenido, exige validación para HTML que deba permanecer actualizado y protege explícitamente las respuestas personalizadas. Una política eficiente establece cómo reutilizar y actualizar; no consiste en aplicar un max-age largo a todas las URL.
Distingue respuestas vigentes, obsoletas y validadas
La caché guarda la respuesta, su cuerpo y las cabeceras relevantes. Mientras conserva su vigencia, puede reutilizarse sin consultar al servidor. Una vez obsoleta, normalmente necesita una interacción de red, salvo que la política permita servir contenido antiguo. La caducidad no elimina inmediatamente el archivo: modifica sus condiciones de reutilización.
La validación comprueba si la representación guardada coincide con la actual. Si coincide, el servidor puede responder 304 Not Modified sin retransmitir el cuerpo. Ahorra bytes, pero sigue requiriendo una solicitud y una respuesta. Una copia local vigente evita ese viaje; un acierto validado y otro sin red no tienen el mismo coste.
La caché privada del navegador difiere de la compartida de un proxy o CDN. Una respuesta reutilizable para una persona puede ser inadecuada para otra. Integra esa distinción en el diseño. La guía de tiempo de respuesta del servidor explica el trabajo del origen: almacenar en caché modifica su frecuencia, no necesariamente la velocidad de la operación sin caché.
Adapta Cache-Control a cada respuesta
Las directivas conceden permisos distintos. no-cache, pese a su nombre, no prohíbe almacenar.
| Directiva | Significado en una respuesta | Decisión adecuada |
|---|---|---|
max-age=N |
Vigencia en segundos | Cuánto tiempo reutilizar sin validar |
s-maxage=N |
Vigencia para cachés compartidas | Separar navegador y CDN |
no-cache |
Validar antes de reutilizar | Mantener actualizado el HTML reutilizable |
no-store |
No almacenar la respuesta | Proteger contenido sensible |
private |
Prohibir almacenamiento compartido | Limitar contenido personal a caché privada |
public |
Permitir almacenamiento compartido, sujeto a otras reglas | Compartir contenido público deliberadamente |
immutable |
La representación no cambiará mientras esté vigente | Archivos con huella de contenido |
must-revalidate |
No reutilizar contenido obsoleto sin validación satisfactoria | Evitar reutilización antigua no validada |
Una cookie no convierte de forma fiable la respuesta en privada. Establece la política y evita que el CDN la anule. private no cifra ni impide guardar en el navegador. Para una respuesta sensible de cuenta que no deba almacenarse, utiliza Cache-Control: no-store y configura también la exclusión de caché compartida.
No acumules directivas mecánicamente: una regla clara se audita mejor que valores contradictorios. Añadir no-store no retira las copias guardadas anteriormente con una política permisiva. Planifica su invalidación por separado. La guía de caché HTTP de MDN explica el modelo.
Cambia la URL cuando cambie el archivo
Una huella de contenido relaciona el nombre con un artefacto concreto. Si cambia app.8f3a1c2d.js, publícalo con otra huella y actualiza el HTML. La URL antigua debe seguir devolviendo los bytes antiguos. Reemplazarlos en una URL inmutable rompe la condición que hacía seguro su plazo largo.
Esta política ilustrativa es habitual para archivos públicos con huella.
Cache-Control: public, max-age=31536000, immutableEl valor equivale a un año en segundos; es una elección, no un umbral obligatorio. El navegador puede expulsar el archivo antes por falta de espacio. Un plazo largo permite reutilizarlo, pero no garantiza disponibilidad sin conexión ni residencia en memoria.
Publica los archivos antes que el HTML que los referencia y conserva versiones anteriores para páginas antiguas y pestañas abiertas. Una importación dinámica tardía puede solicitar un fragmento anterior después del despliegue. Borrar esos archivos inmediatamente puede romper una interacción. Identifica versiones mediante el manifiesto de compilación y aplica una retención adecuada.
Las versiones en parámetros de consulta también distinguen URL si todas las cachés incluyen esos parámetros en su clave. Las huellas en nombres facilitan la inspección. Evita una marca temporal distinta en cada solicitud: impide reutilizar contenido idéntico.
Revalida el HTML con ETag y Last-Modified
El HTML público con URL estable suele beneficiarse de Cache-Control: no-cache y validadores del servidor. Un ETag identifica la versión de una representación y no tiene que ser una huella. Last-Modified indica su modificación. Los valores deben cambiar cuando cambie la representación, incluidas sus variantes pertinentes.
El navegador puede enviar If-None-Match con el ETag guardado. Si coincide, recibe 304; de lo contrario, la representación actual. If-Modified-Since realiza validación temporal con Last-Modified. Si corresponden ambas condiciones, prevalece la de ETag. No fijes el mismo ETag para todas las páginas o versiones.
Para HTML personalizado que puede guardarse en el navegador, pero no en un CDN, un punto de partida es private, no-cache. Para contenido más sensible, elige no-store. Prueba autenticación, autorización y cierre de sesión: las cabeceras no sustituyen los permisos. La configuración estática nunca debe aplicar una política pública a una descarga autenticada.
La validación ahorra bytes sin necesariamente ahorrar todo el cálculo del origen. Si la aplicación genera la respuesta completa para obtener el ETag, puede seguir realizando mucho trabajo. Mide transferencia y procesamiento antes de atribuir una reducción de carga del servidor a la caché.
Configura Apache en un directorio público específico
Este .htaccess corresponde únicamente a un directorio de archivos públicos con huellas de contenido. Requiere Apache HTTP Server 2.4, mod_headers y autorización para esas directivas. No es una política general para subidas, exportaciones privadas o archivos que solo comparten extensión.
La regla reconoce una huella hexadecimal en minúsculas de al menos ocho caracteres antes de una extensión admitida.
# public/assets/.htaccess
<FilesMatch "\.[a-f0-9]{8,}\.(css|js|mjs|png|jpg|jpeg|webp|avif|svg|woff2)$">
Header set Cache-Control "public, max-age=31536000, immutable"
</FilesMatch>Configura el HTML en la aplicación o ubicación que realmente lo genera. Una regla de nombres no cubre necesariamente rutas reescritas. Si un framework, módulo o proxy ya establece Cache-Control, elimina el solapamiento en su origen y revisa duplicados en la respuesta final. Las tablas de cabeceras y redirecciones internas de Apache pueden afectar a la combinación.
Valida en pruebas que los archivos correctos reciben la cabecera esperada. Solicita también un archivo inexistente y un endpoint autenticado. La optimización no debe convertir errores o datos privados en objetos públicos durante un año. En alojamiento administrado, averigua qué capa controla la caché antes de cambiar ajustes ignorados o reemplazados.
Configura Nginx sin ampliar qué puede almacenarse
Utiliza una ruta exclusiva y reserva la política larga para archivos públicos con huellas generadas durante la compilación. Este fragmento se integra en un bloque server existente cuya raíz contiene /assets/. Revisa la prioridad de las ubicaciones frente al enrutamiento actual.
El ejemplo sirve archivos reales y no envía los ausentes a la aplicación.
location ~ ^/assets/.+\.[a-f0-9]{8,}\.(css|js|mjs|png|jpg|jpeg|webp|avif|svg|woff2)$ {
try_files $uri =404;
add_header Cache-Control "public, max-age=31536000, immutable";
}Omitir always es deliberado: no apliques esta política indiscriminadamente a estados de error. Revisa la herencia de add_header en tu versión. Añadir cabeceras en una ubicación anidada puede afectar a las cabeceras de seguridad heredadas; versiones nuevas incorporan controles adicionales. Conserva las necesarias y comprueba la respuesta efectiva.
Ejecuta nginx -t antes de recargar, con los permisos del despliegue. Valida sintaxis, no la seguridad del diseño de caché. Comprueba el comportamiento a través del CDN y en el origen. Una cabecera correcta no basta si una regla posterior la sustituye.
Mantén visibles las variantes y otras cachés
Vary indica qué cabeceras de solicitud distinguen representaciones. Si varían por codificación, idioma u otra cabecera, la clave debe reflejar esa diferencia real. No utilices Vary: Cookie como remedio genérico: puede generar multitud de variantes y no sustituye una política privada o exclusión del almacenamiento compartido.
El CDN tiene claves, plazos e invalidación propios. Purgarlo normalmente no borra copias del navegador. Para cambiar un archivo público inmediatamente, una URL nueva funciona mejor que purgar solo el borde. La guía de CDN y caché perimetral explica la interacción.
Un service worker puede interceptar solicitudes y mantener Cache Storage separadamente de la caché HTTP. Su código antiguo o una estrategia cache-first pueden explicar contenido obsoleto aunque las cabeceras sean correctas. Revisa el worker y el almacenamiento y repite la prueba omitiendo esa capa. No borres indiscriminadamente los datos sin conexión de los usuarios como rutina de despliegue.
Verifica visitas normales, actualizaciones y estados privados
En Network de DevTools, deja Disable cache desmarcado. Visita normalmente, vuelve y revisa cabeceras y transferencia. Una respuesta desde memoria o disco difiere de una respuesta de red 304. Una recarga forzada altera deliberadamente la caché y no debe ser tu única prueba.
Conserva una matriz pequeña para HTML público, archivos con huella, páginas sensibles y URL inexistentes. Documenta el permiso de almacenamiento y cómo se actualiza cada caso. Facilita el mantenimiento y descubre cambios amplios que parecerían inocuos al probar una sola página.
Utiliza GET real para inspeccionar cabeceras desde la consola, porque algunos servidores tratan HEAD de otra forma.
curl -sS -D - -o /dev/null https://example.com/assets/app.8f3a1c2d.jsPublica un archivo modificado, confirma la nueva referencia en HTML y deja una pestaña antigua abierta al probar una función tardía. Separa navegación anónima, sesión iniciada y sesión cerrada. Las páginas privadas no deben convertirse en aciertos compartidos ni un archivo inexistente devolver HTML cacheado.
Anota política y comprobaciones en la lista de rendimiento. Consulta la colección de rendimiento del servidor y elige una navegación repetida representativa para medir. El resultado útil es reutilización segura y actualizaciones fiables, no eliminar una advertencia a costa de contenido antiguo o expuesto.