Empêcher la mise en cache des Scripts requis par RequireJS

Requerjs semble faire quelque chose en interne qui cache les fichiers javascript nécessaires. Si je fais une modification à l'un des fichiers requis, j'ai renommer le fichier pour que les modifications soient appliquées.

le truc courant d'ajouter un numéro de version comme param de querystring à la fin du nom de fichier ne fonctionne pas avec requerjs <script src="jsfile.js?v2"></script>

ce que je cherche, c'est un moyen d'empêcher ce cachetage interne des exigences requises scripts sans avoir à renommer mes fichiers de script à chaque mise à jour.

De La Croix-Plate-Forme Solution:

j'utilise maintenant urlArgs: "bust=" + (new Date()).getTime() pour la suppression automatique de cache pendant le développement et urlArgs: "bust=v2" pour la production où j'incrémente la version codée en dur num après avoir déployé un script requis mis à jour.

Note:

@Dustin Getz mentionné dans une réponse récente selon laquelle les outils de développement GoogleChrome supprimeront les points de rupture lors du débogage lorsque les fichiers Javascript sont rafraîchis en permanence comme ceci. Une solution consiste à écrire debugger; en code pour déclencher un point critique dans la plupart des débogueurs Javascript.

Solutions Spécifiques Au Serveur:

pour des solutions spécifiques qui peuvent mieux fonctionner pour votre environnement serveur tel que Node ou Apache, voir quelques réponses ci-dessous.

290
demandé sur BumbleB2na 2011-11-29 21:30:29

12 réponses

Requerjs peut être configuré pour ajouter une valeur à chacune des urls du script pour la mise en cache.

de la documentation RequireJS ( http://requirejs.org/docs/api.html#config ):

urlArgs : les arguments supplémentaires de chaîne de requête de requête annexés aux URLs qui exigent utilise pour récupérer des ressources. Le plus utile pour mettre en cache buste lorsque le navigateur ou le serveur n'est pas configuré correctement.

exemple, ajouter " v2 "à tous les scripts:

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

pour les besoins du développement, vous pouvez forcer RequireJS à contourner le cache en ajoutant un timestamp:

require.config({
    urlArgs: "bust=" + (new Date()).getTime()
});
440
répondu phil mccullick 2013-03-19 01:42:26

N'utilisez pas urlArgs pour cela!

exige des charges de script qui respectent les en-têtes de cache http. (Les Scripts sont chargés avec un <script> inséré dynamiquement , ce qui signifie que la requête ressemble à n'importe quel ancien actif se charger.)

servez vos ressources javascript avec les en-têtes HTTP appropriés pour désactiver la mise en cache pendant le développement.

en utilisant les urlArgs de require signifie que les points de rupture que vous définissez ne seront pas préservés à travers rafraîchissements; vous finissez par avoir besoin de mettre des déclarations debugger partout dans votre code. Mauvais. J'utilise urlArgs pour les actifs de destruction de cache pendant les mises à niveau de production avec le git sha; alors je peux définir mes actifs pour être mis en cache pour toujours et être garanti de ne jamais avoir des actifs périmés.

en développement, je me moque de toutes les requêtes ajax avec une configuration complexe mockjax , alors je peux servir mon application en mode javascript uniquement avec une 10 Ligne Python http serveur avec tout le cache éteint . Cela m'a permis de passer à une application "entrepreneuriale" assez large avec des centaines de paramètres de service web reposants. Nous avons même un concepteur sous contrat qui peut travailler avec notre base de données de production réelle sans lui donner accès à notre code d'arrière-plan.

54
répondu Dustin Getz 2013-08-09 21:15:12

la solution urlArgs a des problèmes. Malheureusement, vous ne pouvez pas contrôler tous les serveurs proxy qui pourraient se trouver entre vous et le navigateur web de votre utilisateur. Certains de ces serveurs mandataires peuvent malheureusement être configurés pour ignorer les paramètres D'URL lors de la mise en cache de fichiers. Si cela se produit, la mauvaise version de votre fichier JS sera livré à votre utilisateur.

j'ai finalement abandonné et a implémenté mon propre correctif directement dans require.js. Si vous êtes prêt à modifier votre version de la bibliothèque requirejs, cette solution pourrait fonctionner pour vous.

vous pouvez voir le patch ici:

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

une fois ajouté, vous pouvez faire quelque chose comme ça dans votre configuration require:

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

utilisez votre environnement de système ou de serveur pour remplacer buildNumber par un ID de révision / n'affectera pas les fichiers non-JS.

cela fonctionne bien pour mon environnement, mais je réalise que certains utilisateurs préféreraient un préfixe plutôt qu'un suffixe, il devrait être facile de modifier mon commit pour répondre à vos besoins.

mise à jour:

dans la discussion de la requête pull, l'auteur des requirejs suggère que cela pourrait fonctionner comme une solution pour préfixer le numéro de révision:

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

je n'ai pas essayé ceci, mais l'implication est que cela demanderait L'URL suivante:

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

Qui pourrait très bien fonctionner pour beaucoup de gens qui peuvent utiliser un préfixe.

voici quelques questions possibles en double:

RequireJS et de la mise en cache du proxy

exiger.js-comment définir une version sur les modules requis dans le cadre de L'URL?

22
répondu JBCP 2017-05-23 12:34:47

Inspiré par Expiration du cache sur le nécessitent.js data-main nous avons mis à jour notre script de déploiement avec la tâche ant suivante:

<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>

où commence main.js ressemble à:

require.config({
    baseUrl: '/js',
    urlArgs: 'bust=@Revision@',
    ...
});
19
répondu dvtoever 2017-05-23 12:26:27

en production

urlArgs peut causer des problèmes!

l'auteur principal d'requirejs préfère ne pas utiliser urlArgs :

pour les moyens déployés, je préfère mettre la version ou le hachage pour l'ensemble construisez en tant que répertoire de compilation, puis modifiez simplement la configuration baseUrl utilisée pour le projet d'utiliser ce répertoire versionné comme baseUrl . Puis aucun autre fichier ne change, et il aide à éviter certains problèmes de proxy où ils ne peut pas mettre en cache une URL avec une chaîne de requête dessus.

[style mine.]

je suis ce conseil.

en développement

je préfère utiliser un serveur qui cache intelligemment des fichiers qui peuvent changer fréquemment: un serveur qui émet Last-Modified et répond à If-Modified-Since avec 304 le cas échéant. Même un serveur basé sur Node express défini pour servir des fichiers statiques fait cela droit sur la boîte. Il ne nécessite pas de faire quoi que ce soit à mon navigateur, et ne gâche pas les points de rupture.

11
répondu Louis 2013-11-01 16:09:12

j'ai pris ce morceau de AskApache et je l'ai mis dans un seperate .fichier conf de mon serveur web Apache local (dans mon cas /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>

pour le développement cela fonctionne très bien sans besoin de changer le code. Quant à la production, je pourrais utiliser l'approche de @dvtoever.

6
répondu myrho 2013-12-09 20:00:30

Quick Fix pour le Développement

pour le développement, vous pourriez juste désactiver le cache dans les outils Chrome Dev ( désactiver le cache Chrome pour le développement de site web ). La désactivation du cache ne se produit que si la boîte de dialogue dev tools est ouverte, vous n'avez donc pas à vous soucier de basculer cette option chaque fois que vous naviguez régulièrement.

Note: L'utilisation de " urlArgs " est le solution appropriée dans la production afin que les utilisateurs obtiennent le dernier code. Mais cela rend le débogage difficile parce que chrome invalide les points de rupture à chaque rafraîchissement (parce que c'est un "nouveau" fichier qui est servi à chaque fois).

5
répondu Deepak Joy 2017-05-23 12:26:27

Je ne recommande pas d'utiliser urlArgs " pour l'Éclatement de cache avec Requerjs. Comme cela ne résout pas le problème entièrement. La mise à jour d'une version non se traduira par le téléchargement de toutes les ressources, même si vous n'avez qu'à modifier une seule ressource.

pour traiter ce problème, je recommande d'utiliser des modules Grunt comme 'filerev' pour créer la révision no. En plus de cela, j'ai écrit une tâche personnalisée dans Gruntfile pour mettre à jour la révision no là où c'est nécessaire.

Si nécessaire, je peux partager l'extrait de code pour cette tâche.

3
répondu Amit Sagar 2015-03-03 19:35:46

C'est comme ça que je le fais dans Django / flasque (s'adapte facilement à d'autres langues / systèmes VCS):

dans votre config.py (Je l'utilise en python3, donc vous pourriez avoir besoin de modifier l'encodage en python2)

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

puis dans votre modèle:

{% if config.DEBUG %}
     require.config({urlArgs: "bust=" + (new Date().getTime())});
{% else %}
    require.config({urlArgs: "bust=" + {{ config.GIT_HASH|tojson }}});
{% endif %}
  • Ne nécessite pas de manuel processus de construction
  • n'exécute git rev-parse HEAD qu'une fois lorsque l'application démarre, et le stocke dans le config objet
2
répondu Stephen Fuhry 2014-11-26 14:14:02

Dynamique de la solution (sans urlArgs)

il y a une solution simple pour ce problème, de sorte que vous pouvez charger un numéro de révision unique pour chaque module.

vous pouvez sauvegarder les requisjs d'origine.chargez la fonction, écrasez-la avec votre propre fonction et analysez votre url modifiée avec les requêtes originales.Charger à nouveau:

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

Dans notre processus de construction, j'ai utilisé "gulp-rev" pour construire un manifeste fichier avec toutes les révisions de tous les modules qui sont utilisés. Version simplifiée de ma tâche gulfp:

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

cela générera un module AMD avec des numéros de révision à moduleNames, qui est inclus comme 'oRevision' dans la main.js, où vous écrasez les requisjs.la fonction de charge comme indiqué précédemment.

0
répondu mat 2018-09-12 07:43:01

ceci s'ajoute à la réponse acceptée de @phil mccull.

j'utilise sa méthode mais j'automatise aussi le processus en créant un modèle T4 à exécuter avant la construction.

Préconstruire Des Commandes:

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"

enter image description here

modèle T4:

enter image description here

généré Fichier: enter image description here

stocker dans variable avant de requérir.config.js est chargé: enter image description here

référence dans require.config.js:

enter image description here

-1
répondu Zach Painter 2016-01-09 01:36:37

dans mon cas, je voulais charger le même formulaire chaque fois que je clique, Je ne voulais pas les changements que j'ai faits sur le fichier reste. Il peut ne pas être pertinent pour ce post exactement, mais cela pourrait être une solution potentielle du côté du client sans configuration de configuration pour require. Au lieu d'envoyer directement le contenu, vous pouvez faire une copie du fichier requis et garder le fichier intact.

LoadFile(filePath){
    const file = require(filePath);
    const result = angular.copy(file);
    return result;
}
-2
répondu Mahib 2017-03-23 21:04:38