Forza il browser a cancellare la cache


283

C'è un modo in cui posso inserire del codice sulla mia pagina in modo che quando qualcuno visita un sito, cancella la cache del browser, in modo che possano visualizzare le modifiche?

Lingue utilizzate: ASP.NET, VB.NET e ovviamente HTML, CSS e jQuery.


Una bella soluzione o soluzione per "cache chiaro" si possono trovare qui: stackoverflow.com/a/43676353/2008111
Caramba

Risposte:


350

Se si tratta di .csse .jscambia, un modo è quello di "busting della cache" è aggiungendo qualcosa come " _versionNo" al nome del file per ogni versione. Per esempio:

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 in alternativa fallo dopo il nome del file:

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.

Puoi controllare questo link per vedere come potrebbe funzionare.


10
Questa è una soluzione abbastanza buona e può anche essere automatizzata dal tuo sistema di compilazione (e dovrebbe esserlo). Stackoverflow, ad esempio, utilizza questo approccio.
derobert il

7
SO sta usando gli argomenti GET ora.
Saeb Amini,

60
Meglio ancora è mantenere il nome file così com'è, ma aggiungere il numero di versione come parametro querystring, ad es script.js?v=1.2. (O se non stai tenendo traccia delle versioni, usa semplicemente il file dell'ultima modifica, che è ancora più facile da fare). Non sono sicuro se questo è ciò che intendeva il commentatore precedente!
Doin,

5
Come fanno tutti a farlo con il controllo versione? Sembra un vero dolore.
Shawn,

1
Per quanto riguarda il controllo della versione, è possibile eseguire il rendering <link />dinamico dei tag e iniettare la versione dell'applicazione come parametro della stringa di query. In alternativa, alcuni CMS avranno una "versione di risorse client" come impostazione a livello di CMS che viene aggiunta - l'amministratore del sito può aumentare manualmente quella versione nr e gli aggiornamenti del CMS potrebbero anche aggiornarlo automaticamente. In conclusione: è necessario eseguire il rendering dinamico degli URL dei file.
Jeroen,

103

Esamina il controllo della cache e il tag META scade .

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

Un'altra pratica comune è quella di aggiungere stringhe in continua evoluzione alla fine dei file richiesti. Per esempio:

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


44
Questo non sarà di grande aiuto nel caso in cui sia già memorizzato nella cache: poiché è memorizzato nella cache, il server non verrà interrogato e quindi non può rispondere con nessuna cache. Inoltre, quel meta tag in realtà non dovrebbe essere usato, come dice la nota, si romperà con le cache web.
derobert,

1
+1 cosa ha detto derobert. È sempre meglio utilizzare le intestazioni HTTP per suggerire criteri di cache ai client e alle cache Web, ma anche questo non funziona per forzare un ricaricamento della cache.

4
+1 per la tua seconda soluzione. Ho questo problema che la cache deve essere cancellata solo la prima volta dopo che un amministratore ha effettuato un aggiornamento. Questo approccio dovrebbe risolverlo
Jules Colle il

Disabilitare completamente la cache è di solito una pessima idea.
Giordania,

73

Aggiornamento 2012

Questa è una vecchia domanda, ma penso che abbia bisogno di una risposta più aggiornata perché ora c'è un modo per avere un maggiore controllo della cache del sito Web.

Nelle applicazioni Web offline (che in realtà è qualsiasi sito Web HTML5) è applicationCache.swapCache()possibile utilizzare per aggiornare la versione memorizzata nella cache del sito Web senza la necessità di ricaricare manualmente la pagina.

Questo è un esempio di codice della Guida per principianti all'uso della cache dell'applicazione su HTML5 Rocks che spiega come aggiornare gli utenti alla versione più recente del tuo sito:

// 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);

Vedi anche Utilizzo della cache dell'applicazione su Mozilla Developer Network per maggiori informazioni.

Aggiornamento 2016

Le cose cambiano rapidamente sul Web. Questa domanda è stata posta nel 2009 e nel 2012 ho pubblicato un aggiornamento su un nuovo modo di gestire il problema descritto nella domanda. Passarono altri 4 anni e ora sembra che sia già deprecato. Grazie a cgaldiolo per averlo sottolineato nei commenti.

Attualmente, a partire da luglio 2016, lo standard HTML, sezione 7.9, Applicazioni Web offline include un avviso di deprecazione:

Questa funzione è in procinto di essere rimossa dalla piattaforma Web. (Questo è un lungo processo che richiede molti anni.) L'uso di una qualsiasi delle funzionalità dell'applicazione Web offline in questo momento è altamente scoraggiato. Utilizzare invece gli addetti all'assistenza.

Così fa Utilizzando la cache dell'applicazione su Mozilla Developer Network che ho fatto riferimento nel 2012:

Obsoleto
Questa funzione è stata rimossa dagli standard Web. Sebbene alcuni browser possano ancora supportarlo, è in procinto di essere eliminato. Non utilizzarlo in progetti vecchi o nuovi. Le pagine o le app Web che la utilizzano possono interrompersi in qualsiasi momento.

Vedi anche Bug 1204581 - Aggiungi un avviso di deprecazione per AppCache se l'intercettazione di recupero del lavoratore del servizio è abilitata .


1
Ciò implica che è necessario utilizzare e gestire un file manifest della cache?
Sam,

Attenzione: l'interfaccia di Application Cache (AppCache) è stata deprecata
cgaldiolo

59
Quindi, qual è la raccomandazione attuale a partire dal 2017?
Garrett,

il problema principale riscontrato in questo argomento è quando il dispositivo utilizzato dal visualizzatore continua a utilizzare le versioni memorizzate nella cache perché la memoria interna del dispositivo degli utenti si sta esaurendo. sembra bloccato su una versione cache della pagina e non aggiorna alcun elemento sul documento. questo succede solo in Chrome ?? questo è l'unico browser che ho sperimentato.
user2585548

4
2017: utilizzare i lavoratori dell'assistenza.
digitai,

27

Non come tale. Un metodo consiste nell'inviare le intestazioni appropriate durante la consegna del contenuto per forzare il browser a ricaricare:

Assicurarsi che una pagina Web non sia memorizzata nella cache, su tutti i browser.

Se la tua ricerca "cache header"o qualcosa di simile qui su SO, troverai esempi specifici di ASP.NET.

Un altro modo meno pulito ma a volte solo se non puoi controllare le intestazioni sul lato server è aggiungere un parametro GET casuale alla risorsa che viene chiamata:

myimage.gif?random=1923849839

2
È davvero meglio eseguire correttamente la versione dei file. Questo è un grande spreco di larghezza di banda e, probabilmente ancora più importante, rallenta molto il tuo sito.
derobert il

8
Dipende davvero dalla situazione, no? Se si sta programmando un CMS e è necessario assicurarsi che tutte le risorse modificate vengano aggiornate correttamente, a volte non è possibile aggirare una di queste due opzioni.
Pekka,

Soluzioni come questa dovrebbero essere votate in negativo. Sta a noi mantenere l'impronta di CO2 di Internet più bassa possibile.
tempistica del

14

Per le risorse statiche, la corretta memorizzazione nella cache consisterebbe nell'utilizzare i parametri della query con il valore di ogni distribuzione o versione del file. Ciò avrà effetto di svuotare la cache dopo ogni distribuzione.

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

Ecco un esempio di ASP.NET MVC.

<link href="@Url.Content("~/Content/Css/Reset.css")?version=@this.GetType().Assembly.GetName().Version" rel="stylesheet" type="text/css" />

Non dimenticare di aggiornare la versione dell'assembly.


Grazie per questa risposta, ma come fare quando aggiungiamo risorse nella tabella bundle, per favore?
Toregua,

Nel mio caso, questo stava restituendo "0.0.0.0" come versione. Per ottenere la versione della dll dell'app MVC, utilizzare invece questa:?version=@ViewContext.Controller.GetType().Assembly.GetName().Version
CGodo

1
Ho scoperto che questo impedisce a Firefox e Chrome di memorizzare nella cache del contenuto del tutto.
Sam,

10

Ho avuto un problema simile ed è così che l'ho risolto:

  1. Nel index.htmlfile ho aggiunto manifest:

    <html manifest="cache.manifest">
  2. Nella <head>sezione incluso lo script che aggiorna la cache:

    <script type="text/javascript" src="update_cache.js"></script>
  3. Nella <body>sezione ho inserito la funzione onload:

    <body onload="checkForUpdate()">
  4. In cache.manifestho inserito tutti i file che voglio memorizzare nella cache. È importante ora che funzioni nel mio caso (Apache) semplicemente aggiornando ogni volta il commento "versione". È anche un'opzione per nominare i file con "? Ver = 001" o qualcosa alla fine del nome ma non è necessario . La modifica # version 1.01attiva solo l' evento di aggiornamento della cache.

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

    È importante includere punti 1., 2. e 3. solo in index.html. Altrimenti

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

    si verifica perché ogni file "figlio" tenta di memorizzare nella cache la pagina mentre la pagina è già memorizzata nella cache.

  5. Nel update_cache.jsfile ho inserito questo codice:

    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();
    }

Ora basta modificare i file e in manifest è necessario aggiornare il commento della versione. Ora visitando la pagina index.html si aggiorna la cache.

Le parti della soluzione non sono mie ma le ho trovate tramite Internet e messe insieme in modo che funzionino.


Posso sapere dove è scritto CACHE.MANIFEST.
Shweta Gulati,

1
Shweta Gulati Il file manifest deve trovarsi nella stessa cartella del file "indice". Quali sono le volte in cui non funziona?
Wojtek Mazurek,

1
@ShwetaGulati Sì, la cache non rileva le modifiche nei file html - ecco perché devi aggiornare il numero di versione nel file manifest, perché è quello che viene controllato per le modifiche. È davvero difficile aiutarti, perché non conosco i dettagli. Per favore, dimmi se hai messo tutti i file desiderati in cache su manifest? I percorsi dovrebbero essere relativi al file manifest. Puoi darmi l'indirizzo del tuo sito Web e posso dire qual è il problema :)
Wojtek Mazurek,

1
@ShwetaGulati È perché il browser memorizza automaticamente nella cache alcuni file per velocizzare il caricamento della pagina. È un comportamento predefinito e dipende solo dal browser, quindi non è possibile impostarlo in alcun modo. Soprattutto i file js si trovano nell'ambito del browser, perché vengono generalmente utilizzati su tutte le pagine del sito Web, quindi è consigliabile memorizzarli nella cache. Non c'è altro modo che scrivere tutti i nomi dei file nel file manifest per memorizzare nella cache tutti i file. Se ne trovi qualcuno, dimmelo, perché ne ho bisogno anche io :)
Wojtek Mazurek,

1
Il percorso assoluto per i tuoi file non ha importanza. Percorso relativo dall'indirizzo è importante perché il browser invia la richiesta di file. F.ex: ho dominio example.com ed è su serwer names.com. Il mio spazio su di esso è example.names.com. Quindi unisco il mio dominio example.com al mio spazio server example.names.com come reindirizzamento. Per fare ciò ho bisogno di impostare la cartella come obiettivo di questo reindirizzamento. Quindi, se voglio avere diversi siti su example.names.com, creo la cartella "name1", imposto il reindirizzamento e inserisco tutti i miei file all'interno. I percorsi vengono contati da qui. Se ho name1 \ scripts \ test.js nel file manifest, scrivo script \ test.js.
Wojtek Mazurek,

7

Ho avuto un caso in cui avrei scattato foto di clienti online e avrei dovuto aggiornare il div se una foto fosse cambiata. Il browser mostrava ancora la vecchia foto. Quindi ho usato l'hacking di chiamare una variabile GET casuale, che sarebbe unica ogni volta. Qui è se potesse aiutare qualcuno

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

MODIFICA Come sottolineato da altri, seguire è una soluzione molto più efficiente poiché ricaricherà le immagini solo quando vengono modificate, identificando questa modifica in base alla dimensione del file:

<img src="/photos/userid_73.jpg?modified=<? filemtime("/photos/userid_73.jpg")?>"

29
Questo non è affatto elegante, farebbe in modo che il sito ricarichi l'immagine ogni volta che sprechi molto tempo a scaricare risorse, una soluzione migliore sarebbe quella di utilizzare la dimensione del file invece di un numero casuale, questo renderà la cache riconvalida solo quando il file effettivamente cambia
Roberto Arosemena il

8
O un hash dell'immagine byte
Taylor Edmiston

1
Tutto dipende dai requisiti di un utente. Per un gran numero di foto lo scenario sarebbe diverso da alcune foto. Il controllo delle dimensioni del file consentirebbe di risparmiare larghezza di banda, ma aggiungerebbe anche ulteriore elaborazione, rallentando potenzialmente il caricamento della pagina. Nel mio caso in cui le foto stavano cambiando abbastanza frequentemente ed era una decisione aziendale fondamentale che l'utente potesse ottenere quelle più aggiornate, questa era una soluzione perfetta.
Zeeshan,

Potresti renderlo un valore statico anche nella configurazione, questo non è affatto un approccio ideale.
Vedere il

3
<img src = "/ photos / userid_73.jpg? modified = <? = filemtime (" / photos / userid_73.jpg ")?>" sarebbe molto più utile!
Software Fusca,

4

Molte risposte mancano il punto: la maggior parte degli sviluppatori è consapevole che disattivare la cache è inefficiente. Tuttavia, ci sono molte circostanze comuni in cui l'efficienza non è importante e il comportamento predefinito della cache è gravemente rotto.

Questi includono test di script nidificati e iterativi (il più grande!) E soluzioni temporanee al software di terze parti. Nessuna delle soluzioni fornite qui è adeguata per affrontare tali scenari comuni. La maggior parte dei browser Web è una cache troppo aggressiva e non fornisce alcun mezzo ragionevole per evitare questi problemi.



2

L'aggiornamento dell'URL per quanto segue funziona per me:

/custom.js?id=1

Aggiungendo un numero univoco dopo ?id=e incrementandolo per le nuove modifiche, gli utenti non devono premere CTRL + F5per aggiornare la cache. In alternativa, puoi aggiungere l'hash o la versione stringa dell'ora corrente o Epoch after?id=

Qualcosa di simile a ?id=1520606295


1

Ecco la pagina MDSN sull'impostazione della memorizzazione nella cache in 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

1

Non sono sicuro che ciò possa davvero aiutarti, ma è così che la cache dovrebbe funzionare su qualsiasi browser. Quando il browser richiede un file, deve sempre inviare una richiesta al server a meno che non sia presente una modalità "offline". Il server leggerà alcuni parametri come data modificata o etags.

Il server restituirà una risposta di errore 304 per NOT MODIFIED e il browser dovrà utilizzare la sua cache. Se etag non convalida sul lato server o la data modificata è inferiore alla data modificata corrente, il server deve restituire il nuovo contenuto con la nuova data modificata o etags o entrambi.

Se non ci sono dati di memorizzazione nella cache inviati al browser, suppongo che il comportamento sia indeterminato, il browser potrebbe o meno memorizzare nella cache file che non dicono come vengono memorizzati nella cache. Se si impostano i parametri di memorizzazione nella cache nella risposta, memorizzerà correttamente i file nella cache e il server potrebbe scegliere di restituire un errore 304 o il nuovo contenuto.

Così è come dovrebbe essere fatto. L'uso di parametri casuali o il numero di versione negli URL è più simile a un hack di qualsiasi altra 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- scade-header-vs-ETAG /

Dopo aver letto ho visto che c'è anche una data di scadenza. In caso di problemi, è possibile che sia stata impostata una data di scadenza. In altre parole, quando il browser memorizzerà il file nella cache, poiché ha una data di scadenza, non dovrebbe richiederlo di nuovo prima di tale data. In altre parole, non chiederà mai il file al server e non riceverà mai un 304 non modificato. Utilizzerà semplicemente la cache fino al raggiungimento della data di scadenza o alla cancellazione della cache.

Quindi questa è la mia ipotesi, hai una sorta di data di scadenza e dovresti usare gli etag modificati per ultimi o un mix di tutto e assicurarti che non ci sia una data di scadenza.

Se le persone tendono ad aggiornarsi molto e il file non viene cambiato molto, allora potrebbe essere saggio impostare una grande data di scadenza.

I miei 2 centesimi!


1

Ho implementato questa semplice soluzione che funziona per me (non ancora in ambiente di produzione):

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);
        }
    });
}

Ho un piccolo file situato dove sono gli html:

"Versio.txt":

v00.5.0014

Questa funzione è chiamata in tutte le mie pagine, quindi durante il caricamento controlla se il valore della versione di localStorage è inferiore alla versione corrente e fa un

location.reload(true);

... per forzare la ricarica dal server anziché dalla cache.

(ovviamente, invece di localStorage è possibile utilizzare i cookie o altra memoria client persistente)

Ho optato per questa soluzione per la sua semplicità, perché solo il mantenimento di un singolo file "versio.txt" costringe a ricaricare l'intero sito.

Il metodo queryString è difficile da implementare ed è anche memorizzato nella cache (se si cambia da v1.1 a una versione precedente verrà caricato dalla cache, significa che la cache non viene svuotata, mantenendo tutte le versioni precedenti nella cache).

Sono un po 'alle prime armi e apprezzerei il tuo controllo professionale e la recensione per assicurarmi che il mio metodo sia un buon approccio.

Spero che sia d'aiuto.



0

È possibile utilizzare un trucco che consiste nell'aggiungere un parametro / stringa al nome del file nel tag dello script e modificarlo quando si modificano i file.

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

Il browser interpreta l'intera stringa come percorso del file anche se ciò che viene dopo il "?" sono parametri. Quindi adesso succede che la prossima volta che aggiorni il tuo file basta cambiare il numero nel tag dello script sul tuo sito web (Esempio <script src="myfile.js?version=1.0.1"></script>) e ogni browser degli utenti vedrà il file è cambiato e prendere una nuova copia.


0

Forzare i browser a svuotare la cache o ricaricare i dati corretti? Ho provato la maggior parte delle soluzioni descritte in StackOverflow, alcune funzioni, ma dopo un po ', alla fine memorizza nella cache e visualizza il precedente script o file caricato. Esiste un altro modo per svuotare la cache (css, js, ecc.) E funzionare effettivamente su tutti i browser?

Ho scoperto che è possibile ricaricare singolarmente risorse specifiche se si modificano la data e l'ora sui file sul server. "Svuotare la cache" non è così facile come dovrebbe essere. Invece di svuotare la cache sui miei browser, mi sono reso conto che "toccando" i file del server memorizzati nella cache cambierà effettivamente la data e l'ora del file sorgente memorizzato nella cache sul server (testato su Edge, Chrome e Firefox) e la maggior parte dei browser scaricherà automaticamente la maggior parte attuale copia aggiornata di ciò che è presente sul tuo server (codice, grafica anche qualsiasi file multimediale). Ti suggerisco di copiare gli script più recenti sul server e la soluzione "fai la cosa del tocco" prima dell'esecuzione del programma, quindi cambierà la data di tutti i tuoi file problematici in una data e ora più attuali, quindi scaricherà una nuova copia al tuo browser:

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

quindi ... il resto del programma ...

Mi ci è voluto del tempo per risolvere questo problema (poiché molti browser agiscono in modo diverso a comandi diversi, ma controllano tutti l'ora dei file e si confrontano con la copia scaricata nel browser, se data e ora diverse eseguiranno l'aggiornamento), Se si non posso andare nel modo giusto supposto, c'è sempre un'altra soluzione utilizzabile e migliore. I migliori saluti e buon campeggio. A proposito, toccare (); o le alternative funzionano in molti linguaggi di programmazione inclusi in javascript bash sh php e puoi includerli o chiamarli in html.


1
se il file viene modificato, il timestamp è già cambiato, quindi non c'è alcun vantaggio nel forzarlo di nuovo.
Software Fusca,

Il comando touch non modifica affatto il file. Cambia l'attributo di data e ora, convertendolo in una versione più recente ingannando il browser per scaricarlo come nuova copia.
Luis H Cabrejo,

-1

Vuoi cancellare la cache o semplicemente assicurarti che la tua pagina (modificata?) Non sia memorizzata nella cache?

Se quest'ultimo, dovrebbe essere semplice come

<META HTTP-EQUIV="Pragma" CONTENT="no-cache">

Di recente ho letto di questo approccio in un post di Chrome e ho trovato risultati coerenti solo su una manciata di server live, localhost e file condivisi di Windows ... con Firefox 3.6.
danjah
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.