Question

RequireJS semble faire quelque chose en interne que les caches nécessaires fichiers javascript. Si je fais un changement à l'un des fichiers nécessaires, je dois renommer le fichier pour que les modifications à appliquer.

L'astuce commune de annexant un numéro de version en tant que chaîne de requête à la fin param du nom de fichier ne fonctionne pas avec requirejs <script src="jsfile.js?v2"></script>

Ce que je cherche est un moyen d'éviter ce que cache interne de RequireJS scripts nécessaires sans avoir à renommer les fichiers mon script à chaque fois qu'ils sont mis à jour.

Cross-Platform Solution:

J'utilise maintenant urlArgs: "bust=" + (new Date()).getTime() pour le cache-busting automatique au cours du développement et urlArgs: "bust=v2" pour la production où j'incrémenter la version codée en dur num après le déploiement d'un script nécessaire mise à jour.

Remarque:

@Dustin Getz mentionné dans une réponse récente que les outils de développement Chrome chutera pendant le débogage des points d'arrêt lorsque sont actualisés en permanence les fichiers Javascript comme ça. Une solution consiste à debugger; d'écriture dans le code pour déclencher un point d'arrêt dans la plupart des débogueurs JavaScript.

Solutions spécifiques aux serveurs:

Pour des solutions spécifiques qui peuvent travailler mieux pour votre environnement de serveur comme nœud ou Apache, voir quelques-unes des réponses ci-dessous.

Était-ce utile?

La solution

RequireJS peut être configuré pour ajouter une valeur à chacun des scripts pour les urls de contournement du cache.

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

urlArgs : arguments de chaîne de requête supplémentaire ajouté aux URL qui RequireJS utilisations vont chercher des ressources. Le plus utile pour le buste de cache lorsque le navigateur ou serveur n'est pas correctement configuré.

Exemple, annexant "v2" à tous les scripts:

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

Pour des raisons de développement, vous pouvez forcer RequireJS à contourner le cache en ajoutant un horodatage:

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

Autres conseils

Ne pas utiliser urlArgs pour cela!

Exigez script se charge respectent la mise en cache http têtes. (Les scripts sont chargés avec un <script> dynamique inséré, ce qui signifie que les regards de demande comme tout ancien bien se charger.)

Servir vos actifs javascript avec les en-têtes HTTP propres à la mise en cache de désactiver au cours du développement.

L'utilisation de l'exiger urlArgs signifie tout le points d'arrêt définis ne seront pas conservés dans l'actualisation; vous finissez par avoir besoin de mettre des déclarations de debugger partout dans votre code. Mauvais. J'utilise urlArgs pour les actifs de contournement du cache lors des mises à niveau de production avec le sha git; je peux mettre mes biens à être mis en cache pour toujours et être garanti de ne jamais avoir des actifs obsolètes.

En développement, je me moque de toutes les demandes ajax avec une configuration complexe mockjax , je peux servir mon application dans javascript- seul mode avec un python ligne 10 http serveur avec la mise en cache désactivé . Cela a mis à l'échelle pour moi à une assez grande application « enterprisey » avec des centaines de points de terminaison WebService reposant. Nous avons même un concepteur contrat qui peut travailler avec notre base de code de production réel sans lui donner accès à notre code back-end.

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

J'ai finalement abandonné et mon fix implémenté 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 config besoin:

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

Utilisez votre système de construction ou de l'environnement de serveur pour remplacer buildNumber avec un identifiant de révision / version du logiciel / couleur préférée.

comme ceci utilisez nécessitent:

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

PROVOQUERONT besoin de demander ce fichier:

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

Sur notre environnement serveur, nous utilisons les règles de réécriture URL pour dépouiller le buildNumber, et servir le fichier JS correct. De cette façon, nous n'avons pas vraiment à vous soucier de renommer tous nos fichiers JS.

Le patch ignore tout script qui spécifie un protocole, et il n'affectera pas les fichiers non-JS.

Cela fonctionne bien pour mon environnement, mais je me rends compte que certains utilisateurs préfèrent un préfixe plutôt que d'un suffixe, il devrait être facile de modifier mon engagement en fonction de vos besoins.

Mise à jour:

Dans la discussion de la demande de traction, l'auteur suggère requirejs ce travail pourrait comme une solution à préfixer le numéro de révision:

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

Je n'ai pas essayé, mais l'implication est que ce demanderait à l'adresse suivante:

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

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

Voici quelques questions possibles en double:

RequireJS et la mise en cache proxy

require.js - Comment puis-je mettre une version sur les modules nécessaires dans le cadre de l'URL

Inspiré par Expirez cache sur require.js données principale nous avons mis à notre script deploy la tâche fourmi 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>

Si le début de main.js ressemble à:

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

Dans la production

urlArgs peut causer des problèmes!

L'auteur principal de requirejs préfère ne pas utiliser urlArgs :

Pour les actifs déployés, je préfère mettre la version ou hachage pour l'ensemble construire un répertoire de construction, puis il suffit de modifier la configuration utilisée baseUrl pour le projet d'utiliser ce répertoire versionné comme baseUrl. ensuite pas d'autres fichiers changent, et il aide à éviter quelques problèmes proxy où ils ne peut pas mettre en cache une URL avec une chaîne de requête sur elle.

[Non Styling.]

Je suis de cet avis.

En développement

Je préfère utiliser un serveur qui met en cache intelligemment les 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 le EXPRESSES pour servir des fichiers statiques ne ce droit sur la boîte. Il n'a pas besoin de faire quoi que ce soit à mon navigateur, et ne pas gâcher des points d'arrêt.

Je pris cet extrait de AskApache et le mettre dans un séparé fichier .conf de mon serveur web local Apache (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 bien sans avoir besoin de modifier le code. En ce qui concerne la production, je pourrais utiliser @ l'approche dvtoever.

Quick Fix pour le développement

Pour le développement, vous pouvez simplement désactiver le cache dans Outils Chrome Dev ( cache Chrome pour désactivation développement de sites Web ). La désactivation du cache ne se produit que si les outils de dev dialogue est ouvert, donc vous ne devez pas vous soucier de cette option chaque basculement fois que vous faites la navigation régulière.

Remarque: L'utilisation ' urlArgs est la bonne solution dans la production afin que les utilisateurs obtiennent le dernier code. Mais il rend le débogage difficile car chrome Invalide avec des points d'arrêt à chaque rafraîchissement (parce que son « nouveau » être de fichier servi à chaque fois).

Je ne recommande pas d'utiliser ' urlArgs pour le cache de rupture avec RequireJS. Comme cela ne résout pas le problème complètement. La mise à jour d'une version n'entraînera le téléchargement de toutes les ressources, même si vous avez juste changer une seule ressource.

Pour traiter cette question, je vous recommande d'utiliser des modules Grunt comme « filerev » pour la création d'aucune révision. En plus de cela, je l'ai écrit une tâche personnalisée dans Gruntfile de mettre à jour la révision où cela est nécessaire.

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

Voici comment je le fais dans Django / Flask (peut être facilement adapté à d'autres langues / systèmes VCS):

Dans votre config.py (j'utiliser dans python3, vous devrez peut-être modifier le codage en python2)

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

Ensuite, 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 processus de construction manuelle
  • fonctionne uniquement git rev-parse HEAD une fois au démarrage de l'application, et le stocke dans l'objet config

solution dynamique (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 enregistrer la fonction requirejs.load, de la remplacer avec votre propre fonction et analyser votre URL modifiée à nouveau requirejs.load d'origine:

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

Dans notre processus de construction que j'ai utilisé « gulp-rev » pour construire un fichier manifeste avec toute révision de tous les modules qui sont beeing utilisés. Version simplifiée de ma tâche engouffreur:

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 va générer un AMD-module avec les numéros de révision à moduleNames, qui est inclus comme « oRevision » dans les main.js, où vous écrasez la fonction requirejs.load comme indiqué précédemment.

Ceci est en plus de réponse acceptée de @phil mccull.

J'utilise sa méthode mais j'automatiser également le processus en créant un modèle T4 à exécuter de pré-construction.

Pré-commandes de construction:

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"

modèle T4:

Fichier généré: entrer la description d'image ici

magasin dans la variable avant require.config.js est chargé: entrer la description d'image ici

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

Dans mon cas, je voulais charger la même forme chaque fois que je clique, je ne voulais pas les changements que j'ai fait sur les séjours de fichiers. Il ne peut pas pertinent à ce poste exactement, mais cela pourrait être une solution potentielle du côté client sans réglage config pour avoir besoin. Au lieu d'envoyer le contenu directement, vous pouvez faire une copie du fichier requis et garder intact le fichier réel.

LoadFile(filePath){
    const file = require(filePath);
    const result = angular.copy(file);
    return result;
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top