AngularJS désactiver la mise en cache partielle sur la machine dev

j'ai un problème avec la mise en cache des partiels dans AngularJS.

dans ma page HTML j'ai:

<body>
 <div ng-view></div>
<body>

où mes partiels sont chargés.

quand je change le code HTML dans mon partiel, le navigateur charge toujours les anciennes données.

y a-t-il une solution?

209
demandé sur Chris Martin 2013-02-06 03:20:59

13 réponses

pour le développement, vous pouvez également désactiver le cache navigateur-dans les outils Chrome Dev sur le clic droit en bas sur la vitesse et de cocher l'option

Désactiver le cache (alors que les DevTools est ouvert)

mise à jour: dans Firefox il y a la même option dans Debugger -> paramètres -> section avancée (cochée pour la Version 33)

mise à jour 2: Bien que cette option apparaisse dans Firefox certains signalent qu'elle ne fonctionne pas. Je suggérez d'utiliser firebug et de suivre la réponse de hadaytullah.

200
répondu LukeSolar 2014-11-27 12:07:10

en S'appuyant un peu sur la réponse de @Valentyn, voici une façon de toujours vider automatiquement le cache chaque fois que le contenu de la vue ng change:

myApp.run(function($rootScope, $templateCache) {
   $rootScope.$on('$viewContentLoaded', function() {
      $templateCache.removeAll();
   });
});
111
répondu Mark Rajcok 2013-02-06 04:06:12

comme mentionné dans les autres réponses, ici et ici , le cache peut être nettoyé en utilisant:

$templateCache.removeAll();

cependant comme suggéré par Gat oatigrado dans le comment , cela ne semble fonctionner que si le modèle html a été servi sans aucun en-tête de cache.

donc ça marche pour moi:

en angle:

app.run(['$templateCache', function ( $templateCache ) {
    $templateCache.removeAll(); }]);

vous pouvez ajouter des en-têtes de cache de différentes façons, mais voici quelques solutions qui fonctionnent pour moi.

si vous utilisez IIS , ajoutez ceci à votre site web.config:

<location path="scripts/app/views">
  <system.webServer>
    <staticContent>
      <clientCache cacheControlMode="DisableCache" />
    </staticContent>
  </system.webServer>
</location>

si vous utilisez Nginx, vous pouvez ajouter ceci à votre configuration:

location ^~ /scripts/app/views/ {
    expires -1;   
}

Modifier

je viens de réaliser que la question mentionnait dev machine mais j'espère que ce mai encore aider quelqu'un...

37
répondu Chris Foster 2017-05-23 11:47:16

si vous parlez de cache qui a été utilisé pour la mise en cache de gabarits sans recharger la page entière, alors vous pouvez le vider par quelque chose comme:

.controller('mainCtrl', function($scope, $templateCache) {
  $scope.clearCache = function() { 
    $templateCache.removeAll();
  }
});

et dans le markup:

<button ng-click='clearCache()'>Clear cache</button>

et appuyez sur ce bouton pour vider le cache.

31
répondu Valentyn Shybanov 2013-02-05 23:57:03

Solution Pour Firefox 33.1.1) à l'aide de Firebug (22.0.6)

  1. Outils > Outils Internet > Firebug > Ouvrir Firebug.
  2. dans les vues coupe-feu aller à la vue" Net".
  3. un symbole de menu déroulant apparaîtra à côté de" Net " (titre de la vue).
  4. sélectionnez "Disable Browser Cache" dans le menu déroulant.
23
répondu hadaytullah 2014-11-22 23:27:08

cet extrait m'a aidé à me débarrasser de la mise en cache de template

app.run(function($rootScope, $templateCache) {
    $rootScope.$on('$routeChangeStart', function(event, next, current) {
        if (typeof(current) !== 'undefined'){
            $templateCache.remove(current.templateUrl);
        }
    });
});

les détails de l'extrait suivant peuvent être trouvés sur ce lien: http://oncodesign.io/2014/02/19/safely-prevent-template-caching-in-angularjs /

19
répondu Code Prank 2017-11-14 15:24:13

je poste ceci juste pour couvrir toutes les possibilités puisque aucune des autres solutions n'a fonctionné pour moi (ils ont lancé des erreurs dues à des dépendances angular-bootstrap template, entre autres).

pendant que vous développez / déboguez un modèle spécifique, vous pouvez vous assurer qu'il se rafraîchit toujours en incluant un timestamp dans le chemin, comme ceci:

       $modal.open({
          // TODO: Only while dev/debug. Remove later.
          templateUrl: 'core/admin/organizations/modal-selector/modal-selector.html?nd=' + Date.now(),
          controller : function ($scope, $modalInstance) {
            $scope.ok = function () {
              $modalInstance.close();
            };
          }
        });

Note finale ?nd=' + Date.now() dans le templateUrl à la variable.

16
répondu diosney 2015-01-28 16:31:47

comme d'autres l'ont dit, la suppression totale de la mise en cache pour les besoins du dev peut se faire facilement sans changer de code: utilisez un paramètre de navigateur ou un plugin. En dehors de dev, pour vaincre la mise en cache angulaire des templates basés sur les routes, supprimez L'URL du template du cache pendant $routeChangeStart (ou $stateChangeStart, pour UI Router) comme Shayan l'a montré. Cependant, cela n'affecte pas la mise en cache des gabarits chargés par ng-include, car ces gabarits ne sont pas chargés via le routeur.

j'ai voulu être en mesure de hotfix n'importe quel modèle, y compris ceux chargés par ng-include, en production et avoir les utilisateurs reçoivent le hotfix dans leur navigateur rapidement, sans avoir à recharger la page entière. Je ne me soucie pas non plus de vaincre la mise en cache HTTP pour les modèles. La solution est d'intercepter chaque requête HTTP que L'application fait, ignorer ceux qui ne sont pas pour mon application .modèles html, puis Ajouter un paramètre à L'URL du modèle qui change à chaque minute. Notez que l' path-checking est spécifique au path des modèles de votre application. Pour obtenir un intervalle différent, changez le calcul pour le param, ou supprimez le % complètement pour obtenir aucune mise en cache.

// this defeats Angular's $templateCache on a 1-minute interval
// as a side-effect it also defeats HTTP (browser) caching
angular.module('myApp').config(function($httpProvider, ...) {
    $httpProvider.interceptors.push(function() {
        return {
            'request': function(config) {
                config.url = getTimeVersionedUrl(config.url);
                return config;
            }
        };
    });

    function getTimeVersionedUrl(url) {
        // only do for html templates of this app
        // NOTE: the path to test for is app dependent!
        if (!url || url.indexOf('a/app/') < 0 || url.indexOf('.html') < 0) return url;
        // create a URL param that changes every minute
        // and add it intelligently to the template's previous url
        var param = 'v=' + ~~(Date.now() / 60000) % 10000; // 4 unique digits every minute
        if (url.indexOf('?') > 0) {
            if (url.indexOf('v=') > 0) return url.replace(/v=[0-9](4)/, param);
            return url + '&' + param;
        }
        return url + '?' + param;
    }
11
répondu bradw2k 2015-05-15 19:25:23

si vous utilisez un routeur UI, alors vous pouvez utiliser un décorateur et mettre à jour le service $templateFactory et Ajouter un paramètre de chaîne de requête à templateUrl, et le navigateur chargera toujours le nouveau modèle à partir du serveur.

function configureTemplateFactory($provide) {
    // Set a suffix outside the decorator function 
    var cacheBust = Date.now().toString();

    function templateFactoryDecorator($delegate) {
        var fromUrl = angular.bind($delegate, $delegate.fromUrl);
        $delegate.fromUrl = function (url, params) {
            if (url !== null && angular.isDefined(url) && angular.isString(url)) {
                url += (url.indexOf("?") === -1 ? "?" : "&");
                url += "v=" + cacheBust;
            }

            return fromUrl(url, params);
        };

        return $delegate;
    }

    $provide.decorator('$templateFactory', ['$delegate', templateFactoryDecorator]);
}

app.config(['$provide', configureTemplateFactory]);

je suis sûr que vous pouvez obtenir le même résultat en décorant la méthode" quand " dans $routeProvider.

7
répondu Aman Mahajan 2014-12-14 05:26:21

j'ai trouvé que la méthode HTTP interceptor fonctionne assez bien, et permet une flexibilité et un contrôle supplémentaires. En outre, vous pouvez cache-bust pour chaque version de production en utilisant un hachage de version comme variable de buster.

voici à quoi ressemble la méthode dev cachebusting en utilisant Date .

app.factory('cachebustInjector', function(conf) {   
    var cachebustInjector = {
        request: function(config) {    
            // new timestamp will be appended to each new partial .html request to prevent caching in a dev environment               
            var buster = new Date().getTime();

            if (config.url.indexOf('static/angular_templates') > -1) {
                config.url += ['?v=', buster].join('');
            }
            return config;
        }
    };
    return cachebustInjector;
});

app.config(['$httpProvider', function($httpProvider) {
    $httpProvider.interceptors.push('cachebustInjector');
}]);
3
répondu cpreid 2017-03-24 16:55:36

Voici une autre option dans Chrome.

Hit F12 pour ouvrir les outils de développement. Puis Ressources > Cache De Stockage > "151950920 D'Actualisation" Caches .

enter image description here

j'aime cette option parce que je n'ai pas à désactiver le cache comme dans les autres réponses.

1
répondu Jess 2015-08-28 13:52:04

il n'y a pas de solution pour empêcher la mise en cache par navigateur/proxy puisque vous ne pouvez pas avoir le contrôle dessus.

l'autre façon de forcer le contenu frais à vos utilisateurs il pour renommer le fichier HTML! Exactement comme https://www.npmjs.com/package/grunt-filerev fait pour les actifs.

0
répondu Thomas Decaux 2015-03-03 15:11:26

Actualiser le document à toutes les 30 secondes:

<head>
  <meta http-equiv="refresh" content="30">
</head>

w3schools HTML http-equiv attribut

-3
répondu Eran Or 2017-05-15 11:32:35