Domanda

RequireJS sembra di fare qualcosa internamente che le cache necessari file javascript. Se faccio una modifica a uno dei file richiesti, devo rinominare il file in modo che le modifiche da applicare.

Il trucco comune aggiungendo un numero di versione come parametro querystring alla fine del nome del file non funziona con requirejs <script src="jsfile.js?v2"></script>

Quello che sto cercando è un modo per evitare questo di cache interna di RequireJS script necessari senza dover rinominare il mio script file ogni volta che vengono aggiornati.

Cross-Platform Solution:

Ora sto usando urlArgs: "bust=" + (new Date()).getTime() per automatica della cache-busting durante lo sviluppo e urlArgs: "bust=v2" per la produzione dove ho incrementare la versione num hard-coded dopo stendere uno script richiesto aggiornato.

Nota:

@Dustin Getz citato in un recente risposta che Chrome Developer Tools cadranno i punti di interruzione durante il debug quando i file JavaScript sono continuamente aggiornati in questo modo. Una soluzione è quella di debugger; scrivere nel codice per attivare un punto di interruzione nella maggior parte dei debugger Javascript.

Soluzioni specifiche del server:

Per le soluzioni specifiche che possono lavorare meglio per l'ambiente server come nodo o Apache, vedere alcune delle risposte di seguito.

È stato utile?

Soluzione

RequireJS può essere configurato per aggiungere un valore a ogni URL di script per il busting della cache.

Dalla documentazione RequireJS ( http://requirejs.org/docs/api.html#config ):

urlArgs : Extra argomenti stringa di query aggiunto agli URL che RequireJS usa per aggiornare le risorse. La maggior parte utile per la cache busto quando il browser o server non è configurato correttamente.

Esempio, aggiungendo "v2" per tutti gli script:

require.config({
    urlArgs: "bust=v2"
});

Per scopi di sviluppo, è possibile forzare RequireJS per bypassare il nascondiglio aggiungendo un timestamp:

require.config({
    urlArgs: "bust=" + (new Date()).getTime()
});

Altri suggerimenti

Non utilizzare urlArgs per questo!

Richiede carichi di script rispettano http caching intestazioni. (Gli script vengono caricati con un <script> inserita in modo dinamico, il che significa che gli sguardi di richiesta come qualsiasi vecchio risorsa sempre caricato.)

Servite i vostri beni JavaScript con il corretto header HTTP per il caching disabilita durante lo sviluppo.

Utilizzando richiede di urlArgs: qualsiasi punti di interruzione impostati non saranno conservati in tutta rinfresca; si finisce per dover mettere dichiarazioni debugger ovunque nel codice. Male. Io uso urlArgs per le attività di cache-busting durante gli aggiornamenti di produzione con lo sha git; allora posso impostare i miei beni da memorizzare nella cache per sempre e essere garantito di non aver mai beni stantio.

In fase di sviluppo, mi deridono tutte le richieste Ajax con un complesso mockjax configurazione, quindi posso servire la mia app in JavaScript- solo la modalità con un server di pitone http 10 linea con tutto il caching spento . Questo ha scalato per me ad una piuttosto grande applicazione "enterprisey" con centinaia di endpoint webservice riposanti. Abbiamo anche un designer contratto che può lavorare con la nostra base di codice di produzione reale senza dargli accesso al nostro codice di back-end.

La soluzione urlArgs ha dei problemi. Purtroppo non è possibile controllare tutti i server proxy che potrebbero essere tra voi e il browser web del vostro utente. Alcuni di questi server proxy può essere configurato per ignorare purtroppo parametri URL quando la memorizzazione nella cache dei file. In questo caso, la versione errata del file JS verrà trasportato al vostro utente.

Alla fine ho rinunciato e implementato il mio fix direttamente in require.js. Se siete disposti a modificare la versione della libreria requirejs, questo lavoro soluzione potrebbe per voi.

Si può vedere la patch qui:

https://github.com/jbcpollak/requirejs/commit/589ee0cdfe6f719cd761eee631ce68eee09a5a67

Una volta aggiunto, si può fare qualcosa di simile nella configurazione richiede:

var require = {
    baseUrl: "/scripts/",
    cacheSuffix: ".buildNumber"
}

Usa il tuo sistema di compilazione o di ambiente server per sostituire buildNumber con una / versione del software / colore preferito revisione id.

Uso richiedono in questo modo:

require(["myModule"], function() {
    // no-op;
});

causerà richiedere richiedere questo file:

http://yourserver.com/scripts/myModule.buildNumber.js

Sul nostro ambiente server, usiamo le regole di riscrittura degli URL per togliere il numero build, e servire il file JS corretto. In questo modo in realtà non devono preoccuparsi di rinominare tutti i nostri file JS.

La patch ignorerà qualsiasi script che specifica un protocollo, e non influenzerà i file non-JS.

Questo funziona bene per il mio ambiente, ma mi rendo conto che alcuni utenti preferirebbero un prefisso, piuttosto che un suffisso, dovrebbe essere facile da modificare la mia impegnarsi a soddisfare le vostre esigenze.

Aggiornamento:

Nella discussione richiesta di pull, l'autore requirejs suggerire questo lavoro potrebbe come una soluzione per anteporre il numero di revisione:

var require = {
    baseUrl: "/scripts/buildNumber."
};

Non ho provato questo, ma l'implicazione è che questo sarebbe richiedere il seguente URL:

http://yourserver.com/scripts/buildNumber.myModule.js

Il che potrebbe funzionare molto bene per molte persone che possono utilizzare un prefisso.

Ecco alcune possibili domande duplicate:

RequireJS e proxy caching

require.js -? come posso impostare una versione su moduli richiesti come parte dell'URL

Scade cache on require.js data-principale abbiamo aggiornato il nostro script deploy con il seguente compito ant:

<target name="deployWebsite">
    <untar src="${temp.dir}/website.tar.gz" dest="${website.dir}" compression="gzip" />       
    <!-- fetch latest buildNumber from build agent -->
    <replace file="${website.dir}/js/main.js" token="@Revision@" value="${buildNumber}" />
</target>

Quando l'inizio di main.js assomiglia:

require.config({
    baseUrl: '/js',
    urlArgs: 'bust=@Revision@',
    ...
});

Nella produzione

urlArgs può causare problemi!

L'autore principale della requirejs non preferisce usare urlArgs :

Per le attività dispiegate, preferisco mettere la versione o hash per l'intera costruire come una directory di costruzione, poi basta modificare la configurazione utilizzata baseUrl per il progetto di usare quella directory di versione come il baseUrl. Poi nessun altro file cambiano, e aiuta a evitare alcuni problemi di proxy dove Non può memorizzare nella cache un URL con una stringa di query su di esso.

[Styling mio.]

seguo questo consiglio.

In fase di sviluppo

Io preferisco usare un server che memorizza nella cache in modo intelligente i file che possono cambiare di frequente: un server che emette Last-Modified e risponde alle If-Modified-Since con 304 quando opportuno. Anche un server in base esprimere insieme per servire i file statici fa questo a destra, fuori dalla scatola. Non richiede facendo nulla per il mio browser, e non lo fa rovinare i punti di interruzione.

Ho preso questo frammento da AskApache e metterlo in un file separato .conf del mio webserver Apache locale (nel mio caso /etc/apache2/others/preventcaching.conf):

<FilesMatch "\.(html|htm|js|css)$">
FileETag None
<ifModule mod_headers.c>
Header unset ETag
Header set Cache-Control "max-age=0, no-cache, no-store, must-revalidate"
Header set Pragma "no-cache"
Header set Expires "Wed, 11 Jan 1984 05:00:00 GMT"
</ifModule>
</FilesMatch>

Per lo sviluppo di questo funziona bene senza bisogno di modificare il codice. Per quanto riguarda la produzione, potrei usare @ approccio di dvtoever.

Correzione rapida per lo sviluppo

Per lo sviluppo, si può solo disabilitare la cache di Chrome Dev Strumenti ( La cache -sviluppo Disabilitazione Chrome per sviluppo di siti web ). La disattivazione della cache avviene solo se gli strumenti di sviluppo di dialogo è aperto, quindi non c'è bisogno di preoccuparsi alternando questa opzione ogni volta che fate la normale navigazione.

Nota: L'uso ' urlArgs ' è la soluzione adeguata in produzione in modo che gli utenti ottengono l'ultimo codice. Ma rende il debug difficile perché cromati invalida punti di interruzione di ogni aggiornamento (perché è una 'nuova' essere servita file di volta in volta).

Non consiglio usando ' urlArgs ' per la cache di rottura con RequireJS. Poiché questo non risolve completamente il problema. Aggiornamento di una versione non comporterà il download di tutte le risorse, anche se si dispone cambia solo una singola risorsa.

Per gestire questo problema mi consiglia di utilizzare moduli Grunt come 'filerev' per la creazione di revisione n. In cima a questo ho scritto un compito personalizzato in Gruntfile per aggiornare la revisione non ovunque necessario.

In caso di necessità posso condividere il frammento di codice per questo compito.

Questo è come lo faccio in Django / Flask (può essere facilmente adattato ad altri linguaggi / sistemi VCS):

Nel vostro config.py (io uso questo in python3, quindi potrebbe essere necessario modificare la codifica in python2)

import subprocess
GIT_HASH = subprocess.check_output(['git', 'rev-parse', 'HEAD']).strip().decode('utf-8')

Poi, nel tuo template:

{% if config.DEBUG %}
     require.config({urlArgs: "bust=" + (new Date().getTime())});
{% else %}
    require.config({urlArgs: "bust=" + {{ config.GIT_HASH|tojson }}});
{% endif %}
  • non richiede processo di compilazione manuale
  • viene eseguito solo una volta git rev-parse HEAD quando l'applicazione si avvia, e lo memorizza nell'oggetto config

soluzione dinamica (senza urlArgs)

C'è una soluzione semplice per questo problema, in modo che è possibile caricare un numero di revisione unico per ogni modulo.

È possibile salvare la funzione requirejs.load originale, sovrascriverlo con la propria funzione e analizzare il vostro URL modificato al requirejs.load originale di nuovo:

var load = requirejs.load;
requirejs.load = function (context, moduleId, url) {
    url += "?v=" + oRevision[moduleId];
    load(context, moduleId, url);
};

Nel nostro processo di costruzione che ho usato "gulp-rev" per costruire un file manifesto con tutta la revisione di tutti i moduli che sono beeing utilizzati. versione semplificata del mio compito gulp:

gulp.task('gulp-revision', function() {
    var sManifestFileName = 'revision.js';

    return gulp.src(aGulpPaths)
        .pipe(rev())
        .pipe(rev.manifest(sManifestFileName, {
        transformer: {
            stringify: function(a) {
                var oAssetHashes = {};

                for(var k in a) {
                    var key = (k.substr(0, k.length - 3));

                    var sHash = a[k].substr(a[k].indexOf(".") - 10, 10);
                    oAssetHashes[key] = sHash;
                }

                return "define([], function() { return " + JSON.stringify(oAssetHashes) + "; });"
            }
        }
    }))
    .pipe(gulp.dest('./'));
});

questo genererà un processore AMD-modulo con numeri di revisione a moduleNames, che è incluso come 'oRevision' nei main.js, dove si sovrascrive la funzione requirejs.load come indicato in precedenza.

Questo è in aggiunta alla risposta accettato @phil di mccull.

Io uso il suo metodo, ma ho anche automatizzare il processo con la creazione di un modello T4 da eseguire pre-build.

pre-compilazione Comandi:

set textTemplatingPath="%CommonProgramFiles(x86)%\Microsoft Shared\TextTemplating\$(VisualStudioVersion)\texttransform.exe"
if %textTemplatingPath%=="\Microsoft Shared\TextTemplating\$(VisualStudioVersion)\texttransform.exe" set textTemplatingPath="%CommonProgramFiles%\Microsoft Shared\TextTemplating\$(VisualStudioVersion)\texttransform.exe"
%textTemplatingPath% "$(ProjectDir)CacheBuster.tt"

entrare descrizione dell'immagine qui

template T4:

entrare descrizione dell'immagine qui

file generato: entrare descrizione dell'immagine qui

Conservare in variabile prima require.config.js è caricato: entrare descrizione dell'immagine qui

Riferimento in require.config.js:

entrare descrizione dell'immagine qui

Nel mio caso ho voluto caricare la stessa forma ogni volta che clicco, non volevo le modifiche che ho apportato sui soggiorni di file. Non può rilevante a questo post esattamente, ma questo potrebbe essere un potenziale soluzione sul lato client senza impostare configurazione per richiedere. Invece di inviare direttamente i contenuti, è possibile effettuare una copia del file richiesto e mantenere intatto il file vero e proprio.

LoadFile(filePath){
    const file = require(filePath);
    const result = angular.copy(file);
    return result;
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top