2015-03-27 10 views
7

Sto usando lo stack MEAN (mongo, express, angular e node). Sto distribuendo relativamente frequentemente alla produzione ... ogni due giorni. La mia preoccupazione è che sto cambiando il codice lato client e l'API a volte e preferirei non dover garantire la retrocompatibilità dell'API con le versioni precedenti del codice client.Come forzare il ricaricamento del client dopo la distribuzione?

In tale scenario, qual è il modo più efficace per garantire che tutti i client vengano ricaricati quando spingo alla produzione? Ho visto che Evernote per esempio ha un pop-up che dice qualcosa sulla falsariga di ricaricare il tuo browser per l'ultima versione di Evernote. Mi piacerebbe fare qualcosa di simile ... devo seguire il percorso di socket.io o sock.js o mi manca qualcosa di semplice e c'è un modo più semplice per raggiungere questo obiettivo?

risposta

7

Aggiornamento: AppCache è stato ritirato durante l'estate 2015, quindi il seguente non è più la soluzione migliore. La nuova raccomandazione è di utilizzare Service Workers invece. Tuttavia, attualmente i Service Worker sono ancora sperimentali con supporto abbozzato (leggi: probabilmente no) in IE e Safari.

In alternativa, molti strumenti di sviluppo ora incorporano senza soluzione di continuità le tecniche di "busting" di cache-busting e file per risolvere la questione degli OP. WebPack è probabilmente l'attuale leader in questo spazio.


Questo potrebbe essere un buon caso d'uso per l'utilizzo di HTML5 AppCache

Si sarebbe probabilmente desidera automatizzare alcuni di questi passi nei vostri script di distribuzione, ma qui è un codice che potrebbe risultare utile per arrivare iniziato.

Per prima cosa, crea il file manifest dell'appcache. Ciò consentirà inoltre di memorizzare nella cache le risorse nel browser del client fino a quando non modifichi in modo esplicito la data del file manifest dell'appcache.

/app.AppCache:

CACHE MANIFEST 

#v20150327.114142 

CACHE: 
/appcache.js 
/an/image.jpg 
/a/javascript/file.js 
http://some.resource.com/a/css/file.css 

NETWORK: 
* 
/

In app.appcache, il commento on line #v20150327.114142 è come indichiamo al browser che il manifesto è cambiato e le risorse dovrebbero essere ricaricata. Può essere qualsiasi cosa, davvero, purché il file risulti diverso dal browser rispetto alla versione precedente. Durante la distribuzione di un nuovo codice nell'applicazione, questa riga deve essere modificata. Potrebbe anche usare un ID di build.

In secondo luogo, su tutte le pagine che si desidera utilizzare l'AppCache, modificare il tag di intestazione in quanto tale:

<html manifest="/app.appcache"></html> 

Infine, è necessario aggiungere un po 'Javascript per controllare l'AppCache per eventuali modifiche, e se ci sono, fai qualcosa al riguardo. Ecco uno Angular module. Per questa risposta, ecco un esempio di vaniglia:

appcache.js:

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 latest hotness. 
     window.applicationCache.swapCache(); 
     if (confirm('A new version of the application is available. Would you like to load it?')) { 
      window.location.reload(); 
     } 
    } 
    else { 
     // Manifest didn't changed. Don't do anything. 
    } 
}, false); 

In alternativa, se AppCache non funziona per la vostra situazione, una soluzione più ghetto sarebbe quella di creare un semplice endpoint API che restituisce l'ID build attuale o l'ultima data-ora di implementazione. L'applicazione Angular occasionalmente colpisce questo endpoint e confronta il risultato con la sua versione interna e, se diverso, ricarica se stesso.

Oppure, si può considerare uno script live-reload (example), ma, sebbene molto utile per lo sviluppo, non sono sicuro di quanto sia buona idea utilizzare la ricarica live/sul posto delle risorse in produzione.

+0

Wow! AppCache. Penso che potrebbe essere un po 'troppo per quello che sto cercando ... specialmente perché vedo che IE9 non sembra essere supportato e Firefox sembra richiedere il consenso dell'utente. Mi piace molto l'idea della soluzione 'ghetto', tuttavia: controllare un endpoint API a un intervallo impostato e chiamare window.location.reload() se necessario.In realtà sembra bello e semplice per me ... anche se sono sicuro che qualcuno mi dirà che posso fare la stessa cosa con la stessa facilità con socket.io .... – Andrew

+0

sì; puoi farlo con socket.io .. ma questo è un sovraccarico solo per gli aggiornamenti del codice "in tempo reale". Il ping del server su un timeout sembra sufficiente (e meno costoso in termini di risorse: non devi preoccuparti di un sacco di connessioni socket aperte o preoccuparti del bilanciamento del carico mentre aumenti di livello ..) A meno che, ovviamente, la tua app non sia già utilizzata socket.io. Quindi ha più senso. –

+0

Sì, sto pensando la stessa cosa ... troppo in alto. Probabilmente aggiungeremo socket.io nei prossimi mesi, ma penso che andremo con l'approccio ping API fino a quando non lo faremo. Grazie per la tua risposta! – Andrew

0
  1. Provare a limitare i file js/a scadere in tempi più brevi, ovvero: 1 giorni.
  2. Ma nel caso in cui si desidera qualcosa che pop-out e comunicare al vostro utente per ricaricare (Ctrl + F5) proprio browser, quindi è sufficiente fare uno script che popup che notizia se appena modificato alcuni file, marchio l'ip/session che ha appena ricaricato/detto di ricaricare, quindi non sarà infastidito da più popup.
+0

Il punto 1 è giusto. Ho cambiato il tempo di scadenza del CDN per le risorse statiche a 1 giorno da 7 giorni. – Andrew

1

Forse è possibile aggiungere hash al nome del file del codice client. ad es. app-abcd23.js.
Quindi il browser ricaricherà il file invece di scaricarlo dalla cache. oppure puoi semplicemente aggiungere l'hash a url.eg app.js?hash=abcd23 ma alcuni browser potrebbero ancora utilizzare la versione cache.

so che i binari hanno asset-pipline per gestirlo, ma non ho familiarità con MEAN stack. ci dovrebbe essere qualche pacchetto in npm per quello scopo.

E non penso che sia davvero necessario utilizzare socket.io se si desidera notificare all'utente che il codice cliente non è aggiornato. puoi definire la tua versione in entrambi i file html meta tag e js, se non corrispondente, mostrare un popup e dire all'utente di aggiornare.

+0

Grazie! È una SPA però ... quindi non sono sicuro che il metatag html e l'approccio alla versione del file js funzioneranno. È plausibile che l'utente possa lasciare aperta la finestra del browser per una settimana, tornare indietro e iniziare a utilizzare l'app senza ricaricare e il meta tag e la versione del file js rimarranno invariati. Il punto di denominazione del file è buono, ma lo stesso problema: corregge la cache in caso di ricarica ma non se l'utente non ricarica. Destra? – Andrew

+0

sì, aggiungi hash al nome del file è per la cache del browser e cdn. quindi penso di fare una chiamata ajax ogni ora o giorno per vedere se c'è se c'è una nuova versione e quindi aggiornare la pagina utilizzando js potrebbe funzionare per voi. socket.io è ancora troppo per questo. E se vuoi aggiungere cose in tempo reale alla tua app, ti suggerisco di usare firebase o analizzare invece di usare socket.io. – at15

+0

Grazie mille per la tua risposta! – Andrew

0

Mi trovavo di fronte allo stesso problema di recente. Ho risolto questo problema aggiungendo il numero di build della mia app con i miei file js/css. Tutti i miei script e style tag sono stati inclusi da uno script in un comune file include quindi era banale per aggiungere un 'numero di build' alla fine del percorso del file js/css come questo

/foo/bar/main.js?123 

Questa 123 è un numero di cui tengo traccia nel mio stesso file di intestazione. Lo incremento ogni volta che voglio che il client imponga il download di tutti i file js dell'app. Questo mi consente di controllare quando vengono scaricate nuove versioni, ma consente comunque al browser di sfruttare la cache per ogni richiesta successiva alla prima. Questo finché non spingo un altro aggiornamento incrementando il numero di build.

Ciò significa anche che posso avere un'intestazione di scadenza della cache per quanto tempo desidero.

Problemi correlati