AngularJS geliştirici makinesinde kısmi önbelleğe almayı devre dışı bırak


210

AngularJS'de kısmi önbellekleme ile sorunum var.

HTML sayfamda:

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

kısmi yüklerimin olduğu yer.

Kısmi bölümümdeki HTML kodunu değiştirdiğimde, tarayıcı hala eski verileri yükler.

Herhangi bir çözüm var mı?


4
Sadece hızlı bir not: Flask uygulamamın geri gönderdiği önbellek kontrol başlıklarıyla ilgili bir sorunum vardı. Ben ekleyerek sorunu etrafında var app.config.update(SEND_FILE_MAX_AGE_DEFAULT=0)kardeşime karşı flask_app.py. (Diğer web sunucuları için de benzer şeyler olduğunu düşünüyorum).
gatoatigrado

4
Eğer krom kullanıyorsanız sadece yapmak Ctrl+Shift+R(yani Sabit yükle) ve mekanizması önbelleğe ne olursa olsun kullanılan krom bunu görmezden ve stil vb tüm komut dosyalarını yeniden alıp bunu olduğu
snajahi

4
ctrl + shift + R Chrome'da benim için çalışmıyor, ancak geliştirici araçları "ağ" sekmesinde "önbelleği devre dışı bırak" ı tıklamak mükemmel çalışıyor. Benim için bu, aşağıdaki önerilerin çoğu gibi sunucudaki saldırıları kullanarak çözülmemesi gereken bir istemci tarafı sorunudur; "sorunun" bulunduğu istemcide düzeltilmelidir. Sunucuda onarır ve düzeltmeyi unutursanız, üretim olumsuz etkilenebilir.
Ant Kutschera

8
ctrl + shift + R normal istekler için önbelleği atlar. ajax için açısal istekleri ng-include| ng-view| templateUrlkısayol tarafından ele
alınmaz

2
Siteyi ziyaret ederken tüm son kullanıcılardan Ctrl + Shift + R'ye soramazsınız, bu nedenle geliştirme dışı durum için bu sorunun cevabı nedir? "Benim için, bu aşağıdaki önerilerin çoğu gibi sunucuda kesmek kullanarak çözülmesi gereken bir istemci tarafı sorunu" - Kabul etmiyorum, bir web ortamında istemcileri kontrol edemezsiniz, bu nedenle üretim için düzeltme uygulama güdümlü olmalıdır. Bu nedenle kabul ettim: $ rootScope. $ On ('$ viewContentLoaded', function () {$ templateCache.removeAll ();});
Robert Christian

Yanıtlar:


200

Geliştirme için tarayıcı önbelleğini de devre dışı bırakabilirsiniz - Sağ alt taraftaki Chrome Dev Araçları'nda dişli çark simgesini tıklayıp seçeneği işaretleyin

Devre Dışı önbellek (DevTools açıkken)

Güncelleme: Firefox'ta Hata Ayıklayıcı -> Ayarlar -> Gelişmiş Bölüm'de aynı seçenek var (Sürüm 33 için işaretlendi)

Güncelleme 2: Bu seçenek Firefox'ta görünmesine rağmen bazı raporlar çalışmıyor. Firebug kullanmanızı ve hadaytullah cevabını takip etmenizi öneririm.


7
Bu, kod değişikliği gerektirmediği ve OP'nin isteği açısından daha fazla olduğu için kabul edilen cevap olmalıdır. Tabii ki, bir üretim uygulamasının istekleri önbelleğe almasını istersiniz, bu nedenle yukarıdaki milletlerin önerdiği şeyi yapmak, kod bir üretim uygulamasında bırakılırsa sorunlu olabilir.
Aaron Wagner

Firefox gibi diğer tarayıcılar için herhangi bir öneriniz var mı?
Lereveme

Firefox: Hata Ayıklayıcı> Ayarlar'da (dişli) aynı seçenek vardır.
LukeSolar

5
Bu, Firefox'ta çalışmaz. Önbellek devre dışı ve araç kutusu açık olsa bile, şablonlar hala önbelleğe alınır.
Patrick J Collins

4
Önbellekleme üretimi de etkiler mi? Yeni web dosyalarını sunucuya gönderirsem, üretim istemcilerinden gelen sonraki isteklerin önceden yayımlanan önbelleğe alınmış sürümleri yüklemesini ne engeller?
meffect

111

@ Valentyn'in cevabını biraz geliştirerek, ng-view içeriği her değiştiğinde önbelleği her zaman otomatik olarak temizlemenin bir yolu:

myApp.run(function($rootScope, $templateCache) {
   $rootScope.$on('$viewContentLoaded', function() {
      $templateCache.removeAll();
   });
});

@ user252690 Muhtemelen html şablonunun önbellek başlıkları ile gönderilmediğinden de emin olmanız gerekir. Olası düzeltmeler için buraya ve buraya bakın
Chris Foster

30
Biraz uyarı: $ templateCache öğesini boşaltmanın aslında istenmeyen sonuçları olabilir. Örneğin, UI Bootstrap başlatma sırasında doğrudan kısmi $ templateCache öğesine ekler ve daha sonra bunların orada olmasını bekler.
Strille

@Strille Açısal-ui-bootstrap Modal kullanmaya çalışıyordum. Açılır pencere görünmüyordu. çünkü $ templateCache.removeAll (); bunun için herhangi bir düzeltme?
Mukun

4
@Mukun: removeAll () kullanmamaktan başka gördüğüm şekilde kolay bir düzeltme yoktur, bunun yerine temizlemeniz gereken anahtarları silmek için remove () kullanın. Hangi anahtarların silineceğini bilmek için bir tür defter tutmanız gerekir.
Strille

yalnızca belirli kullanıcı arayüzü görüntüleme önbelleği için önbelleği temizlemenin herhangi bir yolu var mı?
Gayan

37

Diğer cevaplarda belirtildiği gibi, burada ve burada , önbellek kullanılarak temizlenebilir:

$templateCache.removeAll();

Tarafından önerildiği gibi Ancak gatoatigrado içinde comment html şablonu herhangi önbellek başlıkları olmadan sunulduğu takdirde, bu sadece işin görünür.

Bu benim için çalışıyor:

Açısal olarak:

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

Önbellek başlıklarını çeşitli şekillerde ekliyor olabilirsiniz, ancak işte benim için çalışan birkaç çözüm var.

Kullanıyorsanız IIS, bunu web.config dosyasına ekleyin:

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

Nginx kullanıyorsanız, bunu config'inize ekleyebilirsiniz:

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

Düzenle

Sorunun devmakineden bahsettiğini fark ettim ama umarım bu hala birine yardımcı olabilir ...


2
Evet, bu orijinal soruya doğrudan cevap vermese de, bu aslında canlı bir web sitesinde önbellek sorununu çözmeme yardımcı oldu.
Andre

31

Tüm sayfayı yeniden yüklemeden şablonların önbelleğe alınması için kullanılan önbellekten bahsediyorsanız, aşağıdaki gibi bir şeyle boşaltabilirsiniz:

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

Ve işaretlemede:

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

Önbelleği temizlemek için bu düğmeye basın.


22

Firebug (22.0.6) kullanan Firefox (33.1.1) çözümü

  1. Araçlar> Web Araçları> Firebug> Firebug'u açın.
  2. Firebug görünümlerinde "Net" görünümüne gidin.
  3. "Net" in (görünümün başlığı) yanında bir açılır menü simgesi görünür.
  4. Açılır menüden "Tarayıcı Önbelleğini Devre Dışı Bırak" ı seçin.

Mac'te Firebug (2.0.11) ve Firefox (38.0.1) üzerinde çalıştı, ancak bu işe yaramadı.
paullb

19

Bu snippet şablon önbelleklemesinden kurtulmamda bana yardımcı oldu

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

Aşağıdaki kod parçasının ayrıntıları bu bağlantıda bulunabilir: http://oncodesign.io/2014/02/19/safely-prevent-template-caching-in-angularjs/


nitpick ama akım ne zaman bir nesne değildir? Hiç orada olmadığından emin değilim amaif (!current) { return; }
Nate-Wilkins

Bu, Angular'ın rota tabanlı şablonları önbelleğe almasını engeller, ancak ng-include'lu kısmi değildir.
bradw2k

16

Bunu sadece tüm olasılıkları kapsamak için gönderiyorum çünkü diğer çözümlerin hiçbiri benim için çalışmadı (diğerleri arasında açısal-bootstrap şablon bağımlılıkları nedeniyle hatalar attılar).

Belirli bir şablonu geliştirirken / hata ayıklarken, yola aşağıdaki gibi bir zaman damgası ekleyerek her zaman yenilenmesini sağlayabilirsiniz:

       $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();
            };
          }
        });

Nihai Not ?nd=' + Date.now()içinde templateUrldeğişken.


1
Daha sonra .value('DEBUG', true)bu satırı etkinleştirmek ya da etkinleştirmemek için a ayarlayabilirsiniz .
diosney

1
Benim Çözüm altında benim ana modülün başlatma fazı dahilinde aşağıdaki kullanmaktı .run(function($rootScope) { $rootScope.DEBUG = true; ...gibi $ rootScope enjekte direktifi dahilinde ve sonra .directive('filter', ['$rootScope', function($rootScope)...ve döndürülen nesne özelliğinde: templateUrl: '/app/components/filter/filter-template.html' + ($rootScope.DEBUG ? '?n=' + Date.now() : ''). Belki .value ('DEBUG', true) yaklaşımınızı geliştirebilirsiniz? Upvoted!
JackLeEmmerdeur

Kullanımı, .value('DEBUG', trueyaptığınızla aynıdır $rootScope, ancak dağınıklık olmadan :) Daha sonra DEBUGnormal bir hizmet olarak denetleyiciye ve sorguya enjekte edebilirsiniz .
diosney

.value(...)Çok karmaşık değilse , kaynak kodunu cevabınızı içerecek şekilde genişletebilir misiniz ? Sanırım arkadaki kavram benim bilmediğim açısal bir en iyi uygulamadır.
JackLeEmmerdeur

1
Bu çözüm İyonik ile çalışırken çok kullanışlıdır. Karaciğeri tekrar faydalı hale getirdiğinden beni çok zaman kazandıracak. Bir ton teşekkürler!
ajuser

11

Diğerlerinin söylediği gibi, önbelleklemeyi tamamen geliştirme amacıyla yenmek kodu değiştirmeden kolayca yapılabilir: bir tarayıcı ayarı veya bir eklenti kullanın. Geliştirici dışında, rota tabanlı şablonların açısal şablon önbelleklemesini yenmek için Shayan'ın gösterdiği gibi $ routeChangeStart (veya UI Router için $ stateChangeStart) sırasında şablon URL'sini önbellekten kaldırın. Ancak, ng-include tarafından yüklenen şablonların önbelleğe alınmasını ETKİLEMEZ çünkü bu şablonlar yönlendirici üzerinden yüklenmez.

Üretimde ng-include tarafından yüklenenler de dahil olmak üzere herhangi bir şablonu düzeltmek istedim ve kullanıcıların tüm sayfayı yeniden yüklemek zorunda kalmadan düzeltmeleri tarayıcılarında hızlı bir şekilde almasını istedim. Ayrıca şablonlar için HTTP önbelleğini yenmekten de endişe etmiyorum. Çözüm, uygulamanın yaptığı her HTTP isteğini durdurmak, uygulamamın .html şablonları için olmayanları yok saymak ve ardından şablonun URL'sine her dakika değişen bir param eklemektir. Yol kontrolünün, uygulamanızın şablonlarının yoluna özgü olduğunu unutmayın. Farklı bir aralık elde etmek için, parametrenin matematiğini değiştirin veya önbellekleme almak için% 'yi tamamen kaldırın.

// 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;
    }

Çözümünüzle ilgileniyorum - bir değişiklik yaptıktan sonra bu kodu iyi mi tutuyorsunuz - yoksa belirli bir süre mi? Sebep - performans konusunda endişe duyar. Ayrıca, yan etki HTTP'yi yener. ? O doğru iyi bir yan etki yoludur demek - yani sen 'düzeltmeyi' sahip olmak için amaçlanan budur Thx
Jamie

1
Önbellek bozma süresini 10 dakikaya çevirdik, ancak bu kodu iyi için bırakıyorum. Böylece her 10 dakikada bir kullanıcı yeni html şablonlarını yeniden yükleyecektir. Şablonlarımı sıcak yama yapma yeteneğini kazanmak için kabul edilebilir bir maliyet olan benim uygulamamız için, ancak bazı uygulamalar için performansı çok fazla düşürecektir. ... HTTP önbelleklemenin de yenilmesi talihsiz bir durum, ancak etag vb. IMO Açısal şablon önbellekleme yeterince yapılandırılamaz.
bradw2k

1
+1 Aynı fikrim vardı, ama sadece localhost için müdahale ettim. Önleme
joshcomley

@joshcomley Yalnızca localhost'ta önbelleğe almayı yenmeniz gerekiyorsa, neden tüm önbelleğe almayı engelleyen bir tarayıcı eklentisi kullanmıyorsunuz?
bradw2k

@ bradw2k Bu şekilde, geliştirme için yararlı olabilecek, önbelleğe alınmış ve önbelleğe alınmamış olanların tam kontrolünü sağlıyorum. Ayrıca tüm tarayıcılarda test ediyorum ve tüm tarayıcılarda ihtiyacım olanı yapan uzantılar yok. Ayrıca, sitede yalnızca önbelleklemenin devre dışı bırakılıp bırakılmadığını söyleyen bir gösterge de bulunabilir, çünkü bazen yalnızca tarayıcıları bir süre devre dışı bırakmak ve test etmek istiyorum.
Joshcomley

8

Kullanıcı arabirimi yönlendiricisi kullanıyorsanız, bir dekoratör kullanabilir ve $ templateFactory hizmetini güncelleyebilir ve templateUrl öğesine bir sorgu dizesi parametresi ekleyebilirsiniz; tarayıcı her zaman yeni şablonu sunucudan yükleyecektir.

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]);

$ RouteProvider içinde "when" yöntemini dekore ederek aynı sonucu elde edebilirsiniz eminim.


Çok daha iyi bir alternatif, açısal js şablonlarını $ templateCache'ye kaydetmek için gulp-angular-templatecache gibi bir eklenti kullanmaktır. Bu gulp-rev ile birlikte kullanılmalıdır. Bir şablon her değiştiğinde, farklı bir düzeltme numarasına sahip yeni bir JavaScript dosyası oluşturulur ve önbellekleme hiçbir zaman sorun olmaz.
Aman Mahajan

3

HTTP önleme yönteminin oldukça iyi çalıştığını ve ek esneklik ve kontrole izin verdiğini buldum. Ayrıca, buster değişkeni olarak bir yayın karması kullanarak her üretim sürümü için önbellek bozabilir.

İşte dev önbellek bozma yöntemi kullanmak gibi görünüyor 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');
}]);

1

İşte Chrome'da başka bir seçenek.

Hit F12açık geliştirici araçları için. Ardından Kaynaklar > Önbellek Depolama > Önbellekleri Yenile .

resim açıklamasını buraya girin

Diğer yanıtlarda olduğu gibi önbelleği devre dışı bırakmak zorunda olmadığım için bu seçeneği beğendim.


Kasım 2016'da Chrome v. 54.0.2840.99'da bunu Application.rather Resources'tan başka bir sekmede buldum.
StackOverflowUser

0

Üzerinde kontrole sahip olamayacağınız için tarayıcı / proxy önbelleğe almayı önlemenin bir çözümü yoktur.

HTML içeriğini yeniden adlandırmak için kullanıcılara taze içerik zorlamanın diğer yolu! Aynen https://www.npmjs.com/package/grunt-filerev varlıklar için yaptığı gibi .


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.