33

Sto iniziando un nuovo progetto in Rails e sembra che il file manifest di application.js stia facendo qualcosa di divertente con i javascript di cui faccio riferimento - memorizza questi file come parte di la pipeline di asset?Cancella la cache dalla pipeline di risorse Rails

Ecco cosa è successo. Ho aggiunto un file JavaScript denominato jquery.autoresize.js nella cartella vendor/Attività/javascript, e poi fatto riferimento il file nelle application.js manifesto come questo:

//= require jquery.autoresize.js 

poi ho iniziato il server rotaie. Ma dopo aver navigato nella mia app, mi sono reso conto di aver accidentalmente aggiunto la versione errata del file jquery.autoresize.js. Così, ho cancellato quel file e poi ho aggiunto la versione corretta alla cartella vendor/assets/javascripts. Ma, con mio orrore, quando ho ricaricato la pagina, sta ancora caricando il vecchio file javascript.

Ho provato a svuotare la cache del browser, quindi a uscire e a riavviare il server Rails, ma inutilmente. Ho violato una soluzione insieme semplicemente rinominando il mio file javascript e facendo riferimento al nuovo nome, che funzionava bene. Ma deve esserci una soluzione migliore per questo.

La nuova pipeline di asset memorizza in cache i file che si riferiscono in qualche modo? In tal caso, come posso cancellare quella cache? Grazie per qualsiasi aiuto!

risposta

48

Suppongo che stiamo parlando dell'ambiente di produzione.

Quando si modifica uno qualsiasi dei propri javascript o fogli di stile nell'ambiente di produzione, è necessario eseguire rake assets:precompile; questa attività compila e comprime i vari file .js e .css e crea i file application.js e application.css caricati dalle visualizzazioni.

E 'possibile che se è stato sostituito con una versione jquery.autoresize.js con una vecchio timestamp, il passo precompilare potrebbe saltare, pensando che la versione compilata è up-to-date. È possibile evitarlo eseguendo prima rake assets:clean, forzandolo a ricostruire tutto nella directory public/assets da zero.

+0

Ah, molto interessante, grazie per i tuoi pensieri. In realtà stavo facendo questo sul mio ambiente di sviluppo locale, e non ho mai eseguito asset di rake: precompilare. Quindi, forse questo lo fa comportarsi in modo diverso? Pensi che l'ambiente di sviluppo potrebbe comportarsi come ho descritto in origine? –

+2

Nell'ambiente di sviluppo, i nomi file con hash non vengono utilizzati, quindi tutto è basato sulle date di modifica dei file. (Fare view-source in un browser per vedere i link di script nell'intestazione HTML.) La mia ipotesi è che nell'ambiente di sviluppo, il file di sostituzione avesse una data di modifica più vecchia, e quindi il browser stava semplicemente usando la sua versione cache. La tua modifica ha aggiornato il tempo di modifica del file, ed è per questo che il browser ha finalmente recuperato la nuova versione. – benzado

+0

Fantastico. Grazie per avermi aiutato a capirlo. Modificherò il contenuto della domanda e altre cose per spiegarti meglio e ti darò credito per l'aiuto. –

23

Rails cancella automaticamente la cache per un singolo file ogni volta che i contenuti vengono modificati. Per cancellare la cache per un singolo file, è sufficiente aprire il file, modificare una riga di codice e salvarla di nuovo. Rails cancellerà la cache per quel file e il browser caricherà il nuovo file la volta successiva che la pagina verrà caricata.

La ragione per cui jquery.autoresize.js stava usando la vecchia versione cache del file era perché la vecchia versione è stata cancellata e quindi la nuova versione è stata copiata e incollata con lo stesso nome nella stessa cartella. Poiché il file stesso non è mai stato modificato, Rails ha continuato a utilizzare il vecchio file che è stato memorizzato nella cache.

Questo perché la pipeline di asset utilizza il fingerprinting per la cache.

L'impronta digitale è una tecnica che rende il nome di un file dipendente sul contenuto del file. Quando il contenuto del file cambia, viene modificato anche il nome file . Per il contenuto statico o non aggiornato modificato, questo fornisce un modo semplice per stabilire se due versioni di un file sono identiche, anche su server diversi o date di distribuzione.

Quando un nome è unico e in base al suo contenuto, le intestazioni HTTP può essere impostato per incoraggiare le cache ovunque (sia a CDN, a fornitori di servizi Internet, in apparecchiature di rete, o nei browser web) per mantenere la propria copia del il contenuto. Quando il contenuto viene aggiornato, l'impronta digitale cambia. In questo modo i client remoti potranno richiedere una nuova copia del contenuto di . Questo è generalmente noto come busting della cache.

La tecnica che Rails utilizza per il rilevamento delle impronte digitali consiste nell'inserire un hash del contenuto nel nome, solitamente alla fine. Ad esempio un file CSS globale.css potrebbe essere rinominato con un digest MD5 del suo contenuto:

global-908e25f4bf641868d8683022a5b62f54.css 

Quindi, se si elimina un file che si sta riferimento nel manifesto, e quindi copiare in un nuovo file con lo stesso nome, la cache il busting non si verifica mai. Quando si modifica il file, viene eseguito il fingerprinting e viene generato un nuovo hash per il nome del file. Questo interrompe la cache per quel file.

Per la storia completa, vedere What is Fingerprinting and Why Should I Care?.

+1

Non penso che sia corretto. L'impronta digitale si basa sul contenuto del file. Se elimini un file e lo sostituisci con uno * diverso * con lo stesso nome, otterrai un'impronta digitale diversa e un nome file diverso. – benzado

+1

Grazie per entrare. Ci hai provato recentemente in uno dei tuoi progetti? Perché posso sicuramente confermare che quando ho creato questa domanda, l'unico modo per caricare il nuovo file dal mio browser è stato quello di modificare una singola riga di codice e salvarla di nuovo. Se funziona per te semplicemente eliminando il file e sostituendolo con uno nuovo con lo stesso nome, mi piacerebbe sentirlo. –

+0

Ho riscontrato un problema di pipeline di asset diverso, che è il modo in cui mi sono imbattuto in questa domanda. Si dice "se si elimina un file a cui si fa riferimento nel manifest e quindi si copia in un nuovo file con lo stesso nome, il busting della cache non si verifica mai"; che * * * è vero solo se il nuovo/vecchio file ha * contenuti identici *, nel qual caso a chi importa quale versione hai? Se stai parlando della modalità di produzione, devi eseguire 'rake assets: precompile' per mettere i file nella directory' public/assets'; questa dovrebbe essere la soluzione a meno che tu non abbia cambiato la configurazione di default. – benzado

6

Io uso config.assets.version = '1.01019' nel mio application.rb per interrompere l'intero cache. Quando voglio spingere una nuova versione completa, incremento la versione e questo fa il trucco. Questo si occupa di quei casi limite in cui Rails non ricompila come asset per qualsiasi motivo.

25

Prova anche rake assets:clobber. Ciò ripristinerà completamente tutto e cancellerà tutte le risorse compilate. Inoltre, ho spesso bisogno di impostare l'ambiente prima di spingere alla produzione andando: RAILS_ENV=production rake assets:precompile.

+0

+1! Questa soluzione ha funzionato per me. Sto sviluppando un processore di asset-pipeline personalizzato e questo fa sì che Sprockets entri nuovamente nel processore. Thx – MegaTux

6

rake tmp:clear ha fatto il trucco per me, sto usando meno binari.

+1

Devo fare anche questo per fare in modo che browserify-rails si aggiorni, altrimenti troverà e userà i vecchi file che sono stati cancellati da allora. 'Rails assets: clean' non funziona per questo. – Ryan

+0

Questo comando rimuoverà anche i file pid nella directory tmp. – caiguanhao