Come posso forzare i client ad aggiornare i file JavaScript?

Al momento stiamo lavorando su una beta privata e quindi stiamo ancora apportando modifiche abbastanza rapide, anche se ovviamente l’utilizzo sta iniziando a salire, rallenteremo questo processo. Detto questo, un problema che stiamo incontrando è che dopo aver distribuito un aggiornamento con nuovi file JavaScript, i browser client usano ancora la versione cache del file e non vedono l’aggiornamento. Ovviamente, in una chiamata di supporto, possiamo semplicemente informarli di fare un aggiornamento di Ctrl F5 per assicurarsi che ottengano i file aggiornati dal server, ma sarebbe preferibile gestirli prima di quel momento.

Il nostro attuale pensiero è semplicemente quello di albind un numero di versione al nome dei file JavaScript e quindi quando vengono apportate modifiche, incrementare la versione sullo script e aggiornare tutti i riferimenti. Questo sicuramente ha portato a termine il lavoro, ma l’aggiornamento dei riferimenti su ogni rilascio potrebbe diventare ingombrante.

Siccome sono sicuro che non siamo i primi a occuparci di questo, ho pensato che lo avrei buttato fuori nella comunità. Come stai assicurando che i client aggiornino la cache quando aggiorni il tuo codice? Se stai utilizzando il metodo descritto sopra, stai utilizzando un processo che semplifica la modifica?

    Per quanto ne so una soluzione comune è aggiungere una ? al collegamento src dello script.

    Per esempio:

      

    Suppongo a questo punto che non ci sia un modo migliore di find-replace per incrementare questi “numeri di versione” in tutti i tag dello script?

    Potresti avere un sistema di controllo della versione che fa per te? La maggior parte dei sistemi di controllo delle versioni ha un modo per iniettare automaticamente il numero di revisione al momento del check-in, per esempio.

    Sarebbe simile a questo:

      

    Certo, ci sono sempre soluzioni migliori come questa .

    Aggiungere l’ora corrente all’URL è davvero una soluzione comune. Tuttavia, se lo desideri, puoi anche gestirlo a livello di server web. Il server può essere configurato per inviare diverse intestazioni HTTP per i file javascript.

    Ad esempio, per forzare la memorizzazione del file nella cache per non più di 1 giorno, si invierà:

     Cache-Control: max-age=86400, must-revalidate 

    Per la versione beta, se si desidera forzare l’utente a ottenere sempre l’ultima, si utilizzerà:

     Cache-Control: no-cache, must-revalidate 

    Google Page-Speed: non includere una stringa di query nell’URL per le risorse statiche. La maggior parte dei proxy, in particolare Squid up attraverso la versione 3.0, non memorizza nella cache le risorse con un “?” nel loro URL anche se un controllo Cache: l’intestazione pubblica è presente nella risposta. Per abilitare il caching del proxy per queste risorse, rimuovere le stringhe di query dai riferimenti alle risorse statiche e invece codificare i parametri nei nomi dei file stessi.

    In questo caso, puoi includere la versione in URL ex: http://abc.com/ v1.2 /script.js e utilizzare apache mod_rewrite per redirect il link a http://abc.com/script.js . Quando si modifica la versione, il browser client aggiornerà il nuovo file.

    Questa risposta ha solo 6 anni di ritardo, ma non vedo questa risposta in molti punti … HTML5 ha introdotto Application Cache, che viene utilizzato per risolvere questo problema. Stavo scoprendo che il nuovo codice server che stavo scrivendo stava bloccando il vecchio javascript memorizzato nei browser delle persone, quindi volevo trovare un modo per far scadere il loro javascript. Usa un file manifest simile a questo:

     CACHE MANIFEST # Aug 14, 2014 /mycode.js NETWORK: * 

    e generare questo file con un nuovo timestamp ogni volta che si desidera che gli utenti aggiornino la propria cache. Come nota a margine, se si aggiunge questo, il browser non si ricaricherà (anche quando un utente aggiorna la pagina) fino a quando il manifest non lo dirà a.

    Che ne dici di aggiungere il file come parametro di caricamento?

      

    Ogni volta che aggiorni il file, il parametro “filever” cambia.

    Che ne dici di quando aggiorni il file e il tuo aggiornamento risulta nella stessa dimensione del file? quali sono le probabilità?

    Non tutti i browser memorizzano nella cache i file con “?” dentro. Quello che ho fatto per assicurarmi che fosse memorizzato nella cache il più ansible, ho incluso la versione nel nome del file.

    Quindi, invece di stuff.js?123 , ho fatto stuff_123.js

    Ho usato mod_redirect (credo) in Apache per have stuff_*.js stuff.js per andare a stuff.js

    Per le pagine ASP.NET sto usando quanto segue

    PRIMA

      

    DOPO (ricarica forzata)

      

    L’aggiunta di DateTime.Now.Ticks funziona molto bene.

    Per ASP.NET suppongo che la prossima soluzione con opzioni avanzate (modalità debug / release, versioni):

    File Js o Css inclusi in questo modo:

      

    Global.JsPostfix e Global.CssPostfix vengono calcolati nel seguente modo in Global.asax:

     protected void Application_Start(object sender, EventArgs e) { ... string jsVersion = ConfigurationManager.AppSettings["JsVersion"]; bool updateEveryAppStart = Convert.ToBoolean(ConfigurationManager.AppSettings["UpdateJsEveryAppStart"]); int buildNumber = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.Revision; JsPostfix = ""; #if !DEBUG JsPostfix += ".min"; #endif JsPostfix += ".js?" + jsVersion + "_" + buildNumber; if (updateEveryAppStart) { Random rand = new Random(); JsPosfix += "_" + rand.Next(); } ... } 

    Se stai generando la pagina che si collega ai file JS, una soluzione semplice aggiunge il timestamp dell’ultima modifica del file ai collegamenti generati.

    Questo è molto simile alla risposta di Huppie, ma funziona nei sistemi di controllo delle versioni senza sostituzione di parole chiave. È anche meglio di aggiungere l’ora corrente, poiché ciò impedirebbe il caching anche quando il file non cambiava affatto.

    La funzione jQuery getScript può anche essere utilizzata per garantire che un file js sia effettivamente caricato ogni volta che viene caricata la pagina.

    Ecco come l’ho fatto:

     $(document).ready(function(){ $.getScript("../data/playlist.js", function(data, textStatus, jqxhr){ startProgram(); }); }); 

    Controlla la funzione su http://api.jquery.com/jQuery.getScript/

    Per impostazione predefinita, $ .getScript () imposta l’impostazione della cache su false. Aggiunge un parametro di query con data e ora all’URL della richiesta per garantire che il browser scarichi lo script ogni volta che viene richiesto.

    Abbiamo creato un SaaS per gli utenti e fornito loro uno script da albind nella loro pagina del sito web, e non è stato ansible albind una versione con lo script poiché l’utente allegherà lo script al loro sito web per funzionalità e non posso forzarlo per cambiare la versione ogni volta che aggiorniamo lo script

    Quindi, abbiamo trovato un modo per caricare la versione più recente dello script ogni volta che l’utente chiama lo script originale

    il link dello script fornito all’utente

      

    il file di script

     if($('script[src^="https://thesaasdomain.com/somejsfile.js?"]').length !== 0) { init(); } else { loadScript("https://thesaasdomain.com/somejsfile.js?" + guid()); } var loadscript = function(scriptURL) { var head = document.getElementsByTagName('head')[0]; var script = document.createElement('script'); script.type = 'text/javascript'; script.src = scriptURL; head.appendChild(script); } var guid = function() { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); return v.toString(16); }); } var init = function() { // our main code } 

    Spiegazione:

    L’utente ha allegato lo script fornito a loro nel proprio sito Web e abbiamo verificato la presenza del token univoco con lo script esistente o non utilizzando il selettore jQuery e, in caso contrario, caricarlo dynamicmente con il token più recente (o versione)

    Si chiama lo stesso script due volte, il che potrebbe essere un problema di prestazioni, ma risolve il problema di forzare lo script a non caricarsi dalla cache senza inserire la versione nel link di script reale dato all’utente o al client

    Disclaimer: non utilizzare se le prestazioni sono un grosso problema nel tuo caso.

    Utilizzare una variabile GET versione per impedire la memorizzazione nella cache del browser.

    L’aggiunta di ?v=AUTO_INCREMENT_VERSION alla fine dell’URL impedisce la memorizzazione nella cache del browser, evitando qualsiasi script memorizzato nella cache.

    Il mio collega ha appena trovato un riferimento a quel metodo subito dopo aver postato (in riferimento a css) a http://www.stefanhayden.com/blog/2006/04/03/css-caching-hack/ . È bello vedere che altri lo stanno usando e sembra funzionare. Suppongo a questo punto che non ci sia un modo migliore di find-replace per incrementare questi “numeri di versione” in tutti i tag dello script?

    Sebbene sia specifico della struttura, Django 1.4 ha questa funzione che funziona in modo simile al collegamento al sito ‘greenfelt’ nella risposta di cui sopra

    In PHP :

     function latest_version($file_name){ echo $file_name."?".filemtime($_SERVER['DOCUMENT_ROOT'] .$file_name); } 

    In HTML :

      

    Come funziona:

    In HTML, scrivi il filepath e il nome come fai, ma solo nella funzione. PHP ottiene la filetime del file e restituisce il filepath+name+"?"+time dell'ultima modifica

    Cache Busting in ASP.NET Core tramite un helper di tag gestirà questo per voi e permetterà al vostro browser di mantenere gli script cache / css fino a quando il file cambia. Aggiungi semplicemente il tag helper asp-append-version = “true” al tag script (js) o link (css):

      

    Dave Paquette ha un buon esempio e spiegazione del busting della cache qui (in fondo alla pagina) Cache Busting

    Una soluzione è quella di aggiungere una stringa di query con un timestamp in esso all’URL durante il recupero della risorsa. Questo sfrutta il fatto che un browser non memorizzerà nella cache le risorse recuperate dagli URL con stringhe di query al loro interno.

    Probabilmente non vuoi che il browser non memorizzi le risorse in ogni caso; è più probabile che vengano salvati nella cache, ma desideri che il browser recuperi una nuova versione del file quando viene reso disponibile.

    La soluzione più comune sembra essere quella di incorporare un timestamp o un numero di revisione nel nome del file stesso. Questo è un po ‘più di lavoro, perché il tuo codice deve essere modificato per richiedere i file corretti, ma significa che, ad esempio, la versione 7 del tuo snazzy_javascript_file.js (cioè snazzy_javascript_file_7.js ) è memorizzata nella cache del browser fino a quando non rilasci la versione 8, e poi il tuo codice cambia per recuperare invece snazzy_javascript_file_8.js .

    La soluzione più semplice? Non lasciare che il browser memorizzi nella cache. Aggiungi l’ora corrente (in ms) come una query.

    (Sei ancora in beta, quindi potresti fare un caso ragionevole per non ottimizzare le prestazioni. Ma YMMV qui.)

    Il vantaggio di utilizzare un file.js?V=1 su un file fileV1.js è che non è necessario memorizzare più versioni dei file JavaScript sul server.

    Il problema che vedo con file.js?V=1 è che potresti avere un codice dipendente in un altro file JavaScript che si interrompe quando usi la nuova versione dei programmi di utilità della libreria.

    Per ragioni di compatibilità con le versioni precedenti, penso che sia molto meglio usare jQuery.1.3.js per le nuove pagine e lasciare che le pagine esistenti utilizzino jQuery.1.1.js , finché non si è pronti ad aggiornare le pagine meno jQuery.1.1.js , se necessario.

    Un modo semplice. Modifica htaccess

     RewriteEngine On RewriteBase / RewriteCond %{REQUEST_URI} \.(jpe?g|bmp|png|gif|css|js|mp3|ogg)$ [NC] RewriteCond %{QUERY_STRING} !^(.+?&v33|)v=33[^&]*(?:&(.*)|)$ [NC] RewriteRule ^ %{REQUEST_URI}?v=33 [R=301,L]