Cómo evitar la memoria caché del navegador para el sitio php

120

Tengo un sitio php ejecutándose en un servidor en la nube. Cuando agrego nuevos archivos css, js o imágenes, el navegador está cargando los mismos viejos archivos js, css e imágenes almacenados en caché.

Mi sitio tiene una etiqueta doctype y meta como se muestra a continuación

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

  <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
  <meta http-equiv="Page-Enter" content="blendTrans(Duration=1.0)">
  <meta http-equiv="Page-Exit" content="blendTrans(Duration=1.0)">
  <meta http-equiv="Site-Enter" content="blendTrans(Duration=1.0)">
  <meta http-equiv="Site-Exit" content="blendTrans(Duration=1.0)">

Debido al doctype y metacódigo anteriores, ¿estoy cargando los mismos archivos almacenados en caché en el navegador en lugar de uno nuevo?

ArrayOutOfBound
fuente
No Cache in all Browsers. También puede hacer un? RandomGeneratedNumber en los archivos que no desea que se almacenen en caché.
Kodemon
2
Probablemente no desee deshabilitar la caché por completo para images / js / css: stackoverflow.com/questions/4206224/…
FoolishSeth
Resistí la tentación de necro, pero por favor, cualquiera que esté considerando esto: detente. Aprenda a controlar y usar el almacenamiento en caché, no solo lo desactive ciegamente debido a un episodio inconveniente. Lea el capítulo sobre el almacenamiento en caché de HTTP La guía definitiva : este libro (y los RFC) debe ser una lectura obligatoria, con una prueba. Aprenda cómo especificar el Último modificado, responder a If-Modified-Since y utilizar la identificación ETag. Luego, cuando se actualiza el activo, los navegadores serán informados cuando ese 304 se convierta en 200 una vez más.
amcgregor

Respuestas:

282

prueba esto

<?php

header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
?>
Codesen
fuente
66
Excepto por "max-age = 0", esos son los encabezados enviados por PHP sin especificar lo anterior en mi instalación. Parece que PHP intenta evitar el almacenamiento en caché del navegador por defecto ...
fast-reflexes
1
Tengo un complemento de WordPress que envía un tema alternativo a versiones anteriores de Internet Explorer y se estaba tropezando mucho en algunos sistemas de almacenamiento en caché. Esta publicación apareció en mi primera búsqueda en Google. Bien jugado.
Imperativo
3
Tenga en cuenta que esto no se puede incrustar dentro de html; Esto debería estar en la parte superior de la página.
Hunter S
9
Nota: Si usa session_start()después, sobrescribirá su encabezado Cache-Control: private, max-age=10800, pre-check=10800porque 180 minutos es el valor predeterminado de session.cache_expire. Si no puede evitar iniciar la sesión, pero necesita deshabilitar el uso de caché session_cache_limiter('private');session_cache_expire(0);.
mgutt
2
@thdoan El segundo parámetro de la headerfunción es un booleano para reemplazar . El parámetro opcional replace indica si el encabezado debe reemplazar un encabezado similar anterior o agregar un segundo encabezado del mismo tipo.
mrReiha
36

Aquí, si desea controlarlo a través de HTML: haga lo siguiente: Opción 1:

<meta http-equiv="expires" content="Sun, 01 Jan 2014 00:00:00 GMT"/>
<meta http-equiv="pragma" content="no-cache" />

Y si quieres controlarlo a través de PHP: hazlo como se muestra a continuación. Opción 2:

header('Expires: Sun, 01 Jan 2014 00:00:00 GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', FALSE);
header('Pragma: no-cache');

Y la opción 2 SIEMPRE ES MEJOR para evitar problemas de almacenamiento en caché basado en proxy.

Ritesh Aryal
fuente
10

Puedes probar esto:

    header("Expires: Tue, 03 Jul 2001 06:00:00 GMT");
    header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
    header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
    header("Cache-Control: post-check=0, pre-check=0", false);
    header("Pragma: no-cache");
    header("Connection: close");

¡Ojalá ayude a prevenir el caché, si lo hay!

Aakanksha
fuente
Esto solo se refiere al almacenamiento en caché de los archivos HTML, ¿verdad? ¿Y no tiene nada que ver con eTag? ¡Gracias!
Sam Levin
44
solo la primera línea debería ser suficiente. La quinta línea es realmente incorrecta y no tiene nada que ver con la respuesta del servidor (es un encabezado de solicitud). la sexta línea no tendrá efecto alguno. podría seguir ...
The Surrican
El enfoque de la escopeta: tira todo a la pared, espera que algo se pegue. Según mi comentario sobre la pregunta en sí, puedo recomendar encarecidamente tomar una copia de HTTP: la guía definitiva y leer el capítulo sobre el almacenamiento en caché. También los RFC, pero leerlos es una habilidad distinta. ("Conexión: cerrar" es una acción hilarante para incluir, deshabilitando la canalización eficiente de solicitudes, o no hará nada, pero sospecho que PHP podría dejarlo pasar.)
amcgregor
7

Tuve problemas con el almacenamiento en caché de mis archivos css. Establecer encabezados en PHP no me ayudó (¿tal vez porque los encabezados tendrían que establecerse en el archivo de hoja de estilo en lugar de la página que lo vincula?).

Encontré la solución en esta página: https://css-tricks.com/can-we-prevent-css-caching/

La solución:

Agregue la marca de tiempo como parte de la consulta del URI para el archivo vinculado.
(Se puede usar para css, js, imágenes, etc.)

Para desarrollo:

<link rel="stylesheet" href="style.css?<?php echo date('Y-m-d_H:i:s'); ?>">

Para la producción (donde el almacenamiento en caché es principalmente bueno):

<link rel="stylesheet" type="text/css" href="style.css?version=3.2">
(y reescribir manualmente cuando sea necesario)

O combinación de estos dos:

<?php
    define( "DEBUGGING", true ); // or false in production enviroment
?>
<!-- ... -->
<link rel="stylesheet" type="text/css" href="style.css?version=3.2<?php echo (DEBUGGING) ? date('_Y-m-d_H:i:s') : ""; ?>">

EDITAR:

O combinación más bonita de esos dos:

<?php
    // Init
    define( "DEBUGGING", true ); // or false in production enviroment
    // Functions
    function get_cache_prevent_string( $always = false ) {
        return (DEBUGGING || $always) ? date('_Y-m-d_H:i:s') : "";
    }
?>
<!-- ... -->
<link rel="stylesheet" type="text/css" href="style.css?version=3.2<?php echo get_cache_prevent_string(); ?>">
Lukas
fuente
Versiones arbitrarias, marcas de tiempo actuales (derrotando el almacenamiento en caché por completo) ... pero no lo único que realmente tiene sentido y funciona, independientemente de una bandera de "depuración" o no. ¿Por qué no estás usando el mtime real del archivo? Entonces, literalmente, nunca necesitarías actualizar el PHP, y los cachés no serían completamente inútilmente fantásticos. O simplemente entregue sus estadísticas con un servidor HTTP configurado correctamente como Nginx o Apache que establezca un Last-Modified y ETag adecuados. Del mismo modo, ese tipo de indicador de "depuración" ya existe ... en el navegador. (Desactivar cachés, actualizar sin caché, cachés vacíos, ...)
amcgregor
5

Prevenir la memoria caché del navegador no es una buena idea dependiendo del caso. Buscando una solución, encontré soluciones como esta:

<link rel="stylesheet" type="text/css" href="meu.css?v=<?=filemtime($file);?>">

El problema aquí es que si el archivo se sobrescribe durante una actualización en el servidor, que es mi escenario, el caché se ignora porque la marca de tiempo se modifica, incluso el contenido del archivo es el mismo.

Utilizo esta solución para obligar al navegador a descargar activos solo si se modifica su contenido:

<link rel="stylesheet" type="text/css" href="meu.css?v=<?=hash_file('md5', $file);?>">
ismavolk
fuente
¡Ay! Sería terrible para el rendimiento y la escalabilidad cargar siempre todos sus archivos CSS / JS en el hilo principal para verificar su tamaño / hash.
Dalin
@Dalin Antes de llorar las lágrimas de Gentoo más rico (una distribución de Linux conocida por "ir rápido" al ser excesivamente compilada desde la fuente y la arquitectura ajustada), registraba una statllamada. Sin caché del sistema de archivos, 16ns, tops? Con caché, confiablemente <8ns. Nanosegundos Y en mi sistema, MD5 puede procesar 754 MiB / s sin parpadear. ( openssl speed md5) Combinado, un archivo CSS de 100 KB tendría una sobrecarga adicional combinada de ... 129µs (microsegundos, 0.1295ms) + 8ns (que no contribuye significativamente al número final) = 129µs.
amcgregor
Tras una consideración adicional, me sorprende que la única respuesta "correcta" (con la carga de mantenimiento más baja, el comportamiento más preciso / confiable) sea la menos votada y rechazada en un solo comentario por motivos tan endebles y poco realistas.
amcgregor
Usted y yo probablemente trabajemos en diferentes sitios web. Pero mantengo mi comentario. Si hay docenas de hilos concurrentes que entregan páginas web en cualquier momento, entonces creo que hay mejores opciones que ni siquiera tendrá que cuestionar si es escalable. hash_file('md5', $deployment_counter)o hash_file('md5', $cache_clear_counter)son los primeros que vienen a la mente.
Dalin