Forzar navegador para borrar caché

283

¿Hay alguna manera de poner algún código en mi página para que cuando alguien visite un sitio, borre la memoria caché del navegador, para que pueda ver los cambios?

Lenguajes utilizados: ASP.NET, VB.NET y, por supuesto, HTML, CSS y jQuery.

Adán
fuente
Aquí puede encontrar una buena solución o solución alternativa para "borrar el caché": stackoverflow.com/a/43676353/2008111
caramba

Respuestas:

350

Si esto se trata .cssy .jscambia, una forma es "reventar la memoria caché" agregando algo como " _versionNo" al nombre del archivo para cada versión. Por ejemplo:

script_1.0.css // This is the URL for release 1.0
script_1.1.css // This is the URL for release 1.1
script_1.2.css // etc.

O bien, hágalo después del nombre del archivo:

script.css?v=1.0 // This is the URL for release 1.0
script.css?v=1.1 // This is the URL for release 1.1
script.css?v=1.2 // etc.

Puede consultar este enlace para ver cómo podría funcionar.

Fermín
fuente
10
Esta es una solución bastante buena e incluso puede ser automatizada por su sistema de compilación (y debería serlo) Stackoverflow, por ejemplo, utiliza este enfoque.
derobert
77
SO está usando argumentos GET ahora.
Saeb Amini
6060
Mejor aún es mantener el nombre de archivo tal cual, pero agregar el número de versión como un parámetro de cadena de consulta, es decir script.js?v=1.2. (O si no realiza un seguimiento de las versiones, simplemente use el archivo con la última hora de modificación, que es aún más fácil de hacer). ¡No estoy seguro si eso es lo que quiso decir el comentarista anterior!
Doin
55
¿Cómo hacen todos con el control de versiones? Parece un verdadero dolor.
Shawn
1
@Shawn Version-control sabio podría renderizar las <link />etiquetas dinámicamente e inyectar la versión de la aplicación como un parámetro de cadena de consulta. Alternativamente, algunos CMS tendrán una "versión de recursos del cliente" como una configuración para todo el CMS que se adjunta: el administrador del sitio puede aumentar manualmente esa versión nr, y las actualizaciones del CMS también podrían actualizarla automáticamente. En pocas palabras: debe representar las URL del archivo dinámicamente.
Jeroen
103

Mire en el control de caché y vence la etiqueta META.

<META HTTP-EQUIV="CACHE-CONTROL" CONTENT="NO-CACHE">
<META HTTP-EQUIV="EXPIRES" CONTENT="Mon, 22 Jul 2002 11:12:01 GMT">

Otra práctica común es agregar cadenas que cambian constantemente al final de los archivos solicitados. Por ejemplo:

<script type="text/javascript" src="main.js?v=12392823"></script>

Sampson
fuente
44
Esto no ayudará mucho en el caso de que ya esté almacenado en caché, ya que está almacenado en caché, el servidor no será consultado y, por lo tanto, no puede responder sin caché. Además, esa metaetiqueta realmente no debería usarse, como dice la nota, se romperá con cachés web.
derobert
1
+1 lo que dijo derobert. Siempre es mejor usar encabezados HTTP para sugerir políticas de caché a clientes y cachés web, pero incluso eso no funciona para forzar una recarga de caché.
44
+1 para tu segunda solución. Tengo este problema de que el caché debe borrarse solo la primera vez después de que un administrador haya realizado una actualización. Este enfoque debería resolver eso
Jules Colle, el
Desactivar el caché por completo suele ser una muy mala idea.
Jordania
73

Actualización 2012

Esta es una pregunta antigua, pero creo que necesita una respuesta más actualizada porque ahora hay una manera de tener más control sobre el almacenamiento en caché del sitio web.

En Offline Web Applications (que es realmente cualquier sitio web HTML5) applicationCache.swapCache()puede usarse para actualizar la versión en caché de su sitio web sin la necesidad de volver a cargar la página manualmente.

Este es un ejemplo de código de la Guía para principiantes sobre el uso de la caché de aplicaciones en HTML5 Rocks que explica cómo actualizar a los usuarios a la versión más reciente de su sitio:

// Check if a new cache is available on page load.
window.addEventListener('load', function(e) {

  window.applicationCache.addEventListener('updateready', function(e) {
    if (window.applicationCache.status == window.applicationCache.UPDATEREADY) {
      // Browser downloaded a new app cache.
      // Swap it in and reload the page to get the new hotness.
      window.applicationCache.swapCache();
      if (confirm('A new version of this site is available. Load it?')) {
        window.location.reload();
      }
    } else {
      // Manifest didn't changed. Nothing new to server.
    }
  }, false);

}, false);

Consulte también Uso del caché de la aplicación en Mozilla Developer Network para obtener más información.

Actualización 2016

Las cosas cambian rápidamente en la Web. Esta pregunta se hizo en 2009 y en 2012 publiqué una actualización sobre una nueva forma de manejar el problema descrito en la pregunta. Pasaron otros 4 años y ahora parece que ya está en desuso. Gracias a cgaldiolo por señalarlo en los comentarios.

Actualmente, a partir de julio de 2016, el Estándar HTML, Sección 7.9, Aplicaciones web sin conexión incluye una advertencia de desaprobación:

Esta característica está en proceso de ser eliminada de la plataforma web. (Este es un proceso largo que lleva muchos años). En este momento, se desaconseja el uso de cualquiera de las funciones de la aplicación web sin conexión. Use trabajadores de servicio en su lugar.

Lo mismo ocurre con el uso del caché de la aplicación en la red de desarrolladores de Mozilla a la que hice referencia en 2012:

En desuso
Esta característica se ha eliminado de los estándares web. Aunque algunos navegadores aún pueden soportarlo, está en proceso de ser eliminado. No lo use en proyectos viejos o nuevos. Las páginas o aplicaciones web que lo usan pueden romperse en cualquier momento.

Consulte también el error 1204581: agregue un aviso de desaprobación para AppCache si la intercepción de recuperación del trabajador de servicio está habilitada .

rsp
fuente
1
¿Esto implica que necesita usar y mantener un archivo de manifiesto de caché?
Sam
Advertencia: la interfaz de Application Cache (AppCache) ha quedado en desuso
cgaldiolo
59
Entonces, ¿cuál es la recomendación actual a partir de 2017?
Garrett
El principal problema que he visto sobre este tema es cuando el dispositivo que usa el visor sigue usando las versiones en caché porque la memoria interna del dispositivo de los usuarios se está llenando. parece que se atasca en una versión en caché de la página y no actualiza ningún elemento del documento. ¿esto solo sucede en Chrome? ese es el único navegador en el que lo he experimentado.
user2585548
44
2017: Empleados de servicios de uso.
digitai
27

No como tal. Un método es enviar los encabezados apropiados al entregar contenido para forzar la recarga del navegador:

Asegurarse de que una página web no esté en caché, en todos los navegadores.

Si busca "cache header"o algo similar aquí en SO, encontrará ejemplos específicos de ASP.NET.

Otra forma menos limpia, pero a veces solo si no puede controlar los encabezados en el lado del servidor, es agregar un parámetro GET aleatorio al recurso que se llama:

myimage.gif?random=1923849839
Pekka
fuente
2
Es realmente mejor versionar correctamente los archivos. Este es un desperdicio bastante grande de ancho de banda y, probablemente lo más importante, ralentiza mucho su sitio.
derobert
8
Eso realmente depende de la situación, ¿no? Si está programando un CMS y necesita asegurarse de que todos los recursos modificados se actualicen correctamente, a veces no hay forma de evitar una de estas dos opciones.
Pekka
Soluciones como esta deberían votarse negativamente. Depende de nosotros mantener la huella de CO2 de Internet lo más baja posible.
sincronización
14

Para recursos estáticos, el almacenamiento en caché correcto sería utilizar parámetros de consulta con el valor de cada implementación o versión de archivo. Esto tendrá el efecto de borrar la memoria caché después de cada implementación.

/Content/css/Site.css?version={FileVersionNumber}

Aquí está el ejemplo de ASP.NET MVC.

<link href="@Url.Content("~/Content/Css/Reset.css")[email protected]().Assembly.GetName().Version" rel="stylesheet" type="text/css" />

No olvides actualizar la versión de ensamblaje.

Paulius Zaliaduonis
fuente
Gracias por esta respuesta, pero ¿cómo hacerlo cuando agregamos recursos en la BundleTable, por favor?
toregua
En mi caso, esto estaba devolviendo "0.0.0.0" como la versión. Para obtener la versión del [email protected]().Assembly.GetName().Version
archivo
1
Descubrí que esto evita que Firefox y Chrome almacenen en caché el contenido por completo.
Sam
10

Tuve un problema similar y así es como lo resolví:

  1. En el index.htmlarchivo he agregado manifiesto:

    <html manifest="cache.manifest">
  2. En la <head>sección incluye script que actualiza la caché:

    <script type="text/javascript" src="update_cache.js"></script>
  3. En la <body>sección he insertado la función onload:

    <body onload="checkForUpdate()">
  4. En cache.manifesthe puesto todos los archivos que quiero almacenar en caché. Es importante ahora que funciona en mi caso (Apache) simplemente actualizando cada vez el comentario de la "versión". También es una opción para nombrar archivos con "? Ver = 001" o algo al final del nombre, pero no es necesario . Cambiar solo # version 1.01activa el evento de actualización de caché.

    CACHE MANIFEST
    # version 1.01
    style.css
    imgs/logo.png
    #all other files
    

    Es importante incluir 1., 2. y 3. puntos solo en index.html. De otra manera

    GET http://foo.bar/resource.ext net::ERR_FAILED

    se produce porque cada archivo "secundario" intenta almacenar en caché la página mientras la página ya está en caché.

  5. En el update_cache.jsarchivo he puesto este código:

    function checkForUpdate()
    {
        if (window.applicationCache != undefined && window.applicationCache != null)
        {
            window.applicationCache.addEventListener('updateready', updateApplication);
        }
    }
    function updateApplication(event)
    {
        if (window.applicationCache.status != 4) return;
        window.applicationCache.removeEventListener('updateready', updateApplication);
        window.applicationCache.swapCache();
        window.location.reload();
    }
    

Ahora solo cambia los archivos y, en el manifiesto, debe actualizar el comentario de la versión. Ahora, visitar la página index.html actualizará el caché.

Las partes de la solución no son mías, pero las encontré a través de Internet y las reuní para que funcionen.

Wojtek Mazurek
fuente
¿Puedo saber dónde está escrito CACHE.MANIFEST?
Shweta Gulati
1
Shweta Gulati El archivo de manifiesto debe estar en la misma carpeta que el archivo "índice". ¿Cuáles son las veces que no funciona?
Wojtek Mazurek
1
@ShwetaGulati Sí, la memoria caché no detecta cambios en los archivos html; es por eso que debe actualizar el número de versión en el archivo de manifiesto, ya que es el que se está buscando cambios. Es realmente difícil ayudarte, porque no conozco los detalles. Por favor, dígame si ha puesto todos los archivos deseados en caché en manifiesto. La ruta debe ser relativa al archivo de manifiesto. Puede darme una dirección de su sitio web y puedo decirle cuál es el problema :)
Wojtek Mazurek
1
@ShwetaGulati Es porque el navegador almacena en caché algunos archivos automáticamente para acelerar la carga de la página. Es un comportamiento predeterminado y depende solo del navegador, por lo que no puede configurarlo de ninguna manera. Especialmente los archivos js están en el alcance del navegador, ya que se usan generalmente en todas las páginas del sitio web, por lo que es aconsejable almacenarlos en caché. No hay otra forma que escribir todos los nombres de archivo en el archivo de manifiesto para almacenar en caché todos los archivos. Si encuentra alguno, dígame, porque yo también lo necesito :)
Wojtek Mazurek
1
La ruta absoluta a sus archivos no importa. La ruta relativa desde la dirección importa porque el navegador envía la solicitud de archivos. F.ex: Tengo el dominio example.com y está en serwer names.com. Mi espacio en él es example.names.com. Así que unir mi dominio example.com a mi espacio de servidor example.names.com como redireccionamiento. Para hacer eso, necesito configurar la carpeta como objetivo de esta redirección. Entonces, si quiero tener varios sitios en example.names.com, creo la carpeta "nombre1", establezco la redirección y coloco todos mis archivos dentro. Los caminos se cuentan desde aquí. Si tengo name1 \ scripts \ test.js en el archivo de manifiesto, escribo scripts \ test.js.
Wojtek Mazurek
7

Tuve un caso en el que tomaría fotos de clientes en línea y necesitaría actualizar el div si se cambia una foto. El navegador todavía mostraba la foto anterior. Así que usé el truco de llamar a una variable GET aleatoria, que sería única cada vez. Aquí está si podría ayudar a alguien

<img src="/photos/userid_73.jpg?random=<?php echo rand() ?>" ...

EDITAR Como lo han señalado otros, seguir es una solución mucho más eficiente ya que volverá a cargar imágenes solo cuando se cambien, identificando este cambio por el tamaño del archivo:

<img src="/photos/userid_73.jpg?modified=<? filemtime("/photos/userid_73.jpg")?>"
zeeshan
fuente
29
Esto no es elegante en absoluto, haría que el sitio vuelva a cargar la imagen cada vez que pierda mucho tiempo descargando recursos, una mejor solución sería usar el tamaño de archivo en lugar de un número aleatorio, esto hará que la caché solo se revalide cuando el archivo realmente cambios
Roberto Arosemena
8
O un hash de los bytes de la imagen
Taylor Edmiston
1
Todo depende de los requisitos del usuario. Para un gran número de fotos, el escenario sería diferente a unas pocas fotos. Verificar el tamaño del archivo ahorraría ancho de banda, pero también agregaría un procesamiento adicional, lo que podría ralentizar la carga de la página. En mi caso, cuando las imágenes cambiaban con bastante frecuencia y era una decisión comercial crítica que el usuario obtuviera las más actualizadas, esta era una solución perfecta.
zeeshan
Incluso podría convertirlo en un valor estático en la configuración, de ninguna manera es un enfoque ideal.
Vidente
3
<img src = "/ photos / userid_73.jpg? modified = <? = filemtime (" / photos / userid_73.jpg ")?>" sería mucho más útil!
Fusca Software
4

Muchas respuestas están perdiendo el punto: la mayoría de los desarrolladores son conscientes de que desactivar el caché es ineficiente. Sin embargo, hay muchas circunstancias comunes en las que la eficiencia no es importante y el comportamiento predeterminado de la memoria caché está muy dañado.

Estos incluyen pruebas de guiones iterativos anidados (¡el más grande!) Y soluciones alternativas de software de terceros. Ninguna de las soluciones dadas aquí es adecuada para abordar tales escenarios comunes. La mayoría de los navegadores web son demasiado agresivos y no proporcionan medios razonables para evitar estos problemas.

Juan
fuente
2

La actualización de la URL a lo siguiente funciona para mí:

/custom.js?id=1

Al agregar un número único después ?id=e incrementarlo para nuevos cambios, los usuarios no tienen que presionar CTRL + F5para actualizar el caché. Alternativamente, puede agregar una versión hash o string de la hora actual o Epoch after?id=

Algo como ?id=1520606295

nPcomp
fuente
1

Aquí está la página MDSN sobre la configuración del almacenamiento en caché en ASP.NET.

Response.Cache.SetExpires(DateTime.Now.AddSeconds(60))
Response.Cache.SetCacheability(HttpCacheability.Public)
Response.Cache.SetValidUntilExpires(False)
Response.Cache.VaryByParams("Category") = True

If Response.Cache.VaryByParams("Category") Then
   '...
End If
Dave Swersky
fuente
1

No estoy seguro de si eso realmente podría ayudarlo, pero así es como el almacenamiento en caché debería funcionar en cualquier navegador. Cuando el navegador solicita un archivo, siempre debe enviar una solicitud al servidor a menos que haya un modo "fuera de línea". El servidor leerá algunos parámetros como la fecha de modificación o etags.

El servidor devolverá una respuesta de error 304 para NO MODIFICADO y el navegador tendrá que usar su caché. Si el etag no se valida en el lado del servidor o la fecha de modificación es inferior a la fecha de modificación actual, el servidor debe devolver el nuevo contenido con la nueva fecha de modificación o etags o ambos.

Si no se envían datos de almacenamiento en caché al navegador, supongo que el comportamiento es indeterminado, el navegador puede o no almacenar archivos que no indican cómo se almacenan en caché. Si configura los parámetros de almacenamiento en caché en la respuesta, almacenará en caché sus archivos correctamente y el servidor puede optar por devolver un error 304 o el nuevo contenido.

Asi es como debería de hacerse. Usar parámetros aleatorios o números de versión en las URL es más como un truco que cualquier otra cosa.

http://www.checkupdown.com/status/E304.html http://en.wikipedia.org/wiki/HTTP_ETag http://www.xpertdeveloper.com/2011/03/last-modified-header-vs- expire-header-vs-etag /

Después de leer, vi que también hay una fecha de caducidad. Si tiene problemas, puede ser que tenga una fecha de caducidad configurada. En otras palabras, cuando el navegador almacenará en caché su archivo, ya que tiene una fecha de caducidad, no debería tener que volver a solicitarlo antes de esa fecha. En otras palabras, nunca solicitará el archivo al servidor y nunca recibirá un 304 no modificado. Simplemente usará el caché hasta que se alcance la fecha de caducidad o se borre el caché.

Supongo que tiene una fecha de caducidad y debe usar etags modificados por última vez o una combinación de todos ellos y asegurarse de que no haya fecha de caducidad.

Si la gente tiende a actualizarse mucho y el archivo no cambia mucho, entonces sería aconsejable establecer una gran fecha de vencimiento.

¡Mis 2 centavos!

Loïc Faure-Lacroix
fuente
1

Implementé esta solución simple que funciona para mí (aún no en el entorno de producción):

function verificarNovaVersio() {
    var sVersio = localStorage['gcf_versio'+ location.pathname] || 'v00.0.0000';
    $.ajax({
        url: "./versio.txt"
        , dataType: 'text'
        , cache: false
        , contentType: false
        , processData: false
        , type: 'post'
     }).done(function(sVersioFitxer) {
        console.log('Versió App: '+ sVersioFitxer +', Versió Caché: '+ sVersio);
        if (sVersio < (sVersioFitxer || 'v00.0.0000')) {
            localStorage['gcf_versio'+ location.pathname] = sVersioFitxer;
            location.reload(true);
        }
    });
}

Tengo un pequeño archivo ubicado donde están los html:

"versio.txt":

v00.5.0014

Esta función se llama en todas mis páginas, por lo que, al cargarla, comprueba si el valor de la versión de localStorage es inferior a la versión actual y hace un

location.reload(true);

... para forzar la recarga desde el servidor en lugar de la memoria caché.

(obviamente, en lugar de localStorage puede usar cookies u otro almacenamiento persistente del cliente)

Opté por esta solución por su simplicidad, ya que solo mantener un solo archivo "versio.txt" obligará a recargar el sitio completo.

El método queryString es difícil de implementar y también se almacena en caché (si cambia de v1.1 a una versión anterior se cargará desde el caché, entonces significa que el caché no se vacía, manteniendo todas las versiones anteriores en caché).

Soy un poco novato y agradecería su revisión y revisión profesional para garantizar que mi método sea un buen enfoque.

Espero eso ayude.

Seak
fuente
0

Hay un truco que puede usarse: el truco consiste en agregar un parámetro / cadena al nombre del archivo en la etiqueta del script y cambiarlo cuando el archivo cambia.

<script src="myfile.js?version=1.0.0"></script>

El navegador interpreta la cadena completa como la ruta del archivo aunque lo que viene después del "?" Son parámetros. Entonces, lo que sucede ahora es que la próxima vez que actualice su archivo simplemente cambie el número en la etiqueta del script en su sitio web (Ejemplo <script src="myfile.js?version=1.0.1"></script>) y cada navegador de usuarios verá que el archivo ha cambiado y obtendrá una nueva copia.

Joish
fuente
0

¿Forzar a los navegadores a borrar el caché o recargar los datos correctos? He probado la mayoría de las soluciones descritas en stackoverflow, algo de trabajo, pero después de un tiempo, finalmente almacena en caché y muestra el script o archivo cargado anteriormente. ¿Hay alguna otra forma de borrar el caché (css, js, etc.) y realmente funcione en todos los navegadores?

Descubrí que hasta ahora se pueden recargar recursos específicos individualmente si cambias la fecha y la hora en tus archivos en el servidor. "Borrar caché" no es tan fácil como debería ser. En lugar de borrar el caché en mis navegadores, me di cuenta de que "tocar" los archivos del servidor en caché en realidad cambiará la fecha y la hora del archivo de origen en caché en el servidor (Probado en Edge, Chrome y Firefox) y la mayoría de los navegadores descargarán automáticamente la mayoría copia actual actualizada de lo que está en su servidor (código, gráficos, cualquier multimedia también). Le sugiero que simplemente copie las secuencias de comandos más recientes en el servidor y la solución "haga lo táctil" antes de que se ejecute su programa, por lo que cambiará la fecha de todos sus archivos problemáticos a la fecha y hora más actual, luego descargará una copia nueva a su navegador:

<?php
   touch('/www/sample/file1.css');
   touch('/www/sample/file2.js');
?>

entonces ... el resto de tu programa ...

Me tomó algo de tiempo resolver este problema (ya que muchos navegadores actúan de manera diferente a los diferentes comandos, pero todos verifican la hora de los archivos y se comparan con la copia descargada en su navegador, si la fecha y la hora son diferentes, se actualizarán), si usted no puede ir por el supuesto camino correcto, siempre hay otra solución utilizable y mejor. Saludos cordiales y feliz campamento. Por cierto toque (); o las alternativas funcionan en muchos lenguajes de programación incluidos en javascript bash sh php y puede incluirlos o llamarlos en html.

Luis H Cabrejo
fuente
1
Si el archivo se modifica, la marca de tiempo ya se cambiará de todos modos, por lo que no es beneficioso forzarlo nuevamente.
Fusca Software
El comando táctil no cambia el archivo en absoluto. Cambia el atributo de fecha y hora, convirtiéndolo en una versión más nueva engañando al navegador para descargarlo como una nueva copia.
Luis H Cabrejo
-1

¿Desea borrar el caché o simplemente asegurarse de que su página actual (¿cambiada?) No esté en caché?

Si es lo último, debería ser tan simple como

<META HTTP-EQUIV="Pragma" CONTENT="no-cache">
Tim Crone
fuente
Leí acerca de este enfoque recientemente en una publicación de Chrome, y solo encontré resultados consistentes en un puñado de servidores en vivo, localhost y archivos compartidos de Windows ... con Firefox 3.6.
danjah