AngularJSは開発マシンの部分キャッシュを無効にします


210

AngularJSでパーシャルをキャッシュすることに問題があります。

私のHTMLページには次のものがあります。

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

私のパーシャルがロードされる場所。

パーシャルのHTMLコードを変更しても、ブラウザはまだ古いデータをロードします。

回避策はありますか?


4
簡単なメモ:Flaskアプリケーションが送り返していたキャッシュ制御ヘッダーに関連する問題がありました。をに追加app.config.update(SEND_FILE_MAX_AGE_DEFAULT=0)して問題を回避しましたflask_app.py。(他のWebサーバーにも同様のものが存在すると思います)。
gatoatigrado 2013

4
あなたはしているが、クロムを使用している場合だけで行うCtrl+Shift+R(すなわちハードリロード)とクロムはそれを無視し、スタイルシートなど、すべてのスクリプトを再取得します使用されているキャッシュどんなメカニズムに関係なく
snajahi

4
Chromeではctrl + shift + Rは機能しませんが、開発者ツールの[ネットワーク]タブで[キャッシュを無効にする]をクリックすると完全に機能します。私にとって、これはクライアント側の問題であり、以下の多くの提案のようにサーバーのハックを使用して解決すべきではありません。「問題」が存在するクライアントで修正する必要があります。サーバーで修正し、修正を忘れると、本番環境に悪影響を及ぼす可能性があります。
Ant Kutschera 2015

8
ctrl + shift + Rは、通常のリクエストではキャッシュをバイパスします。の角度から行われたajaxリクエストng-include| ng-view| templateUrlこのショートカットでは処理されません
アンドレ・Werlang

2
サイトにアクセスするときにすべてのエンドユーザーにCtrl + Shift + Rを要求することはできないので、開発以外の場合のこの質問に対する答えは何ですか?「私にとって、これはクライアント側の問題であり、以下の多くの提案のようにサーバーのハックを使用して解決するべきではありません」-私は同意しません。Web環境でクライアントを制御できないため、本番環境での修正アプリケーション主導である必要があります。そのため、私は受け入れました:$ rootScope。$ on( '$ viewContentLoaded'、function(){$ templateCache.removeAll();});
Robert Christian

回答:


200

開発の場合は、ブラウザーのキャッシュを非アクティブ化することもできます-右下のChrome Dev Toolsで歯車を右クリックしてオプションにチェックを入れます

キャッシュを無効にする(DevToolsが開いている間)

更新:Firefoxでは、デバッガ->設定->詳細セクションに同じオプションがあります(バージョン33でチェック)

更新2:このオプションはFirefoxに表示されますが、一部のレポートは機能しません。私は、firebugを使用して、ハデイタッラーの回答に従うことをお勧めします。


7
これは、コードの変更を必要とせず、OPの要求の要点であるので、受け入れられるべき答えです。もちろん、プロダクションアプリでリクエストをキャッシュする必要があるので、上記の人々が提案したことを実行すると、コードがプロダクションアプリに残っている場合、問題が生じる可能性があります。
アーロンワグナー

Firefoxのような他のブラウザーに対する提案はありますか?
Lereveme 2014年

Firefoxの場合:[デバッガ]> [設定](歯車)には同じオプションがあります。
LukeSolar 2014年

5
これはFirefoxでは機能しません。キャッシュが無効でツールボックスが開いている場合でも、テンプレートはキャッシュされます。
Patrick J Collins

4
キャッシングは制作にも影響しますか?新しいWebファイルをサーバーにプッシュした場合、プロダクションクライアントからの後続のリクエストで、事前に公開されたキャッシュバージョンが読み込まれないのはなぜですか?
meffect

111

@Valentynの回答に少し基づいて、ng-viewコンテンツが変更されるたびに常に自動的にキャッシュをクリアする1つの方法を次に示します。

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

@ user252690おそらく、HTMLテンプレートがキャッシュヘッダー付きで送信されていないことも確認する必要があります。可能な修正についてはここここを参照してください
クリスフォスター

30
ちょっとした警告: $ templateCacheを空にすると、実際には意図しない結果になる可能性があります。たとえば、UI Bootstrapは初期化中にデフォルトのパーシャルを$ templateCacheに直接追加し、後でそれらがそこにあることを期待します。
Strille、2014

@Strille私はangular-ui-bootstrap Modalを使用しようとしていました。ポップアップは表示されませんでした。$ templateCache.removeAll(); それに対する修正?
Mukun、2014年

4
@Mukun:removeAll()を使用しない以外は、私がそれを見る方法を簡単に修正することはできませんが、代わりに、remove()を使用して、クリアする必要のあるキーを削除します。削除するキーを知るには、何らかの簿記が必要になります。
Strille、2014年

特定のuiビューキャッシュに対してのみキャッシュをクリアする方法はありますか?
ガイアン

37

他の回答で述べたように、ここここでは、次のコマンドを使用してキャッシュをクリアできます。

$templateCache.removeAll();

ただし、コメントgatoatigradoによって示唆されているように、これは、HTMLテンプレートがキャッシュヘッダーなしで提供された場合にのみ機能するように見えます。

これは私にとってはうまくいきます:

角度で:

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

さまざまな方法でキャッシュヘッダーを追加している可能性がありますが、ここで私に役立つ解決策をいくつか紹介します。

を使用している場合IISは、これをweb.configに追加します。

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

Nginxを使用している場合は、これを設定に追加できます。

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

編集する

私は質問がdevマシンについて言及していることを認識しましたが、うまくいけばこれはまだ誰かを助けるかもしれません...


2
はい、これは元の質問に直接回答していませんが、実際には、ライブWebサイトのキャッシュの問題を解決するのに役立ちました。
アンドレ

31

ページ全体を再読み込みせずにテンプレートのキャッシュに使用されているキャッシュについて話している場合は、次のような方法で空にすることができます。

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

そしてマークアップでは:

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

そして、このボタンを押してキャッシュをクリアします。


22

Firebug(22.0.6)を使用するFirefox(33.1.1)のソリューション

  1. 「ツール」>「Webツール」>「Firebug」>「Firebugを開く」。
  2. Firebugビューで「ネット」ビューに移動します。
  3. ドロップダウンメニューの記号が[ネット](ビューのタイトル)の横に表示されます。
  4. ドロップダウンメニューから[ブラウザキャッシュを無効にする]を選択します。

MacでFirebug(2.0.11)とFirefox(38.0.1)を試してみましたが、これは機能しませんでした。
paullb 2015年

19

このスニペットは、テンプレートのキャッシュを取り除くのに役立ちました

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

次のスニペットの詳細は、このリンクにあります。http//oncodesign.io/2014/02/19/safely-prevent-template-caching-in-angularjs/


nitpickですが、現在はオブジェクトではありませんか?それがそこにないことも確かではありませんがif (!current) { return; }
Nate-Wilkins 14

これは、Angularのルートベースのテンプレートのキャッシングを無効にしますが、ng-includeされたパーシャルは無効にします。
bradw2k

16

他のソリューションはどちらもうまくいかなかったので、すべての可能性をカバーするためにこれを投稿しています(とりわけ、角度付きブートストラップテンプレートの依存関係によるエラーが発生しました)。

特定のテンプレートを開発またはデバッグしているときに、次のようにパスにタイムスタンプを含めることで、常に更新されるようにすることができます。

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

変数の最後?nd=' + Date.now()に注意してくださいtemplateUrl


1
後で.value('DEBUG', true)、その行を有効にするかどうかを設定できます。
diosney 2015

1
私の解決策は、メインモジュールの下の初期化フェーズ内で.run(function($rootScope) { $rootScope.DEBUG = true; ...、次にディレクティブ内で$ rootScopeを挿入.directive('filter', ['$rootScope', function($rootScope)...し、返されたオブジェクトプロパティに以下を使用することtemplateUrl: '/app/components/filter/filter-template.html' + ($rootScope.DEBUG ? '?n=' + Date.now() : '')でした。.value( 'DEBUG'、true)アプローチを詳しく説明できるでしょうか?賛成です!
JackLeEmmerdeur

の使用方法は .value('DEBUG', trueと同じですが、$rootScope煩雑になることはありません:)後でDEBUGコントローラに注入して、通常のサービスとしてクエリを実行できます。
diosney

.value(...)洗練されていなければ、ソースコードを拡張してThingyを含めることはできますか?背後にあるコンセプトは、私には知られていない角度のベストプラクティスだと思います。
JackLeEmmerdeur

1
このソリューションは、Ionicを使用する場合に非常に役立ちます。livereloadが再び役立つので、時間を大幅に節約できます。トンありがとう!
ajuser 2015

11

他の人が言ったように、開発の目的でキャッシュを完全に無効にすることは、コードを変更せずに簡単に行うことができます。ブラウザの設定またはプラグインを使用します。開発以外では、ルートベースのテンプレートのAngularテンプレートキャッシングを無効にするには、Shayanが示したように、$ routeChangeStart(またはUIルーターの場合は$ stateChangeStart)中にテンプレートURLをキャッシュから削除します。ただし、これらのテンプレートはルーターを介して読み込まれないため、ng-includeによって読み込まれたテンプレートのキャッシュには影響しません。

ng-includeによって読み込まれたものを含むすべてのテンプレートを運用環境で修正し、ユーザーがページ全体を再読み込みすることなく、ブラウザーで修正プログラムをすばやく受信できるようにしたいと考えていました。また、テンプレートのHTTPキャッシングを無効にすることも心配していません。解決策は、アプリが行うすべてのHTTPリクエストをインターセプトし、アプリの.htmlテンプレートにないものを無視し、毎分変化するテンプレートのURLにパラメーターを追加することです。パスチェックはアプリのテンプレートのパスに固有であることに注意してください。別の間隔を取得するには、パラメーターの計算を変更するか、%を完全に削除してキャッシュを取得しません。

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

私はあなたの解決策に興味があります-変​​更を加えた後、このコードを永久に保持しますか、それとも一定期間保持しますか?理由-パフォーマンスが心配されます。また、副作用がHTTPを無効にすることに言及しました。あなたはそれが正しいの良い副作用の道であることを意味する-あなたは「修正プログラム」を持っているために、意図したものである意味Thxを?
ジェイミー

1
キャッシュの無効化の長さを10分に戻しましたが、このコードはそのままにしておきます。したがって、ユーザーは10分ごとに新しいHTMLテンプレートを再読み込みします。私のビジネスアプリでは、テンプレートをホットパッチする機能を取得するのに許容できるコストですが、一部の種類のアプリでは明らかにパフォーマンスが低下しすぎます。... HTTPキャッシングも無効になっているのは残念ですが、etagなどを無効にせずにAngularテンプレートキャッシングをインテリジェントに無効にする方法はありません。IMO Angularテンプレートのキャッシュは十分に構成可能ではありません。
bradw2k

1
+1私は同じ考えを持っていましたが、私はlocalhostのみをインターセプトします。あなたはここにインターセプタの私の実装を見ることができます:overengineer.net/...
joshcomley

@joshcomley localhostのキャッシュを無効にするだけの場合は、すべてのキャッシュを無効にするブラウザプラグインを使用しないのはなぜですか。
bradw2k 2016年

@ bradw2kこの方法で、何をキャッシュし、何をキャッシュしないかを完全に制御できます。これは、開発に役立ちます。また、すべてのブラウザでテストを行っていますが、すべてのブラウザに必要な拡張機能があるわけではありません。開発中のサイトに、キャッシュを無効にするかどうかを示すインジケーターを表示することもできます。これは、ブラウザー全体でしばらくの間無効にしてテストしたい場合があるためです。
joshcomley 2016年

8

UIルーターを使用している場合、デコレーターを使用して$ templateFactoryサービスを更新し、クエリ文字列パラメーターをtemplateUrlに追加すると、ブラウザーは常にサーバーから新しいテンプレートを読み込みます。

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の "when"メソッドを装飾することで同じ結果が得られると思います。


はるかに優れた代替策は、gulp-angular-templatecacheのようなプラグインを使用して、角度のjsテンプレートを$ templateCacheに登録することです。これはgulp-revと一緒に使用する必要があります。テンプレートが変更されるたびに、異なるリビジョン番号の新しいJavaScriptファイルが作成され、キャッシュが問題になることはありません。
アマンマハジャン2015

3

HTTPインターセプターメソッドはかなりうまく機能し、柔軟性と制御を追加できることがわかりました。さらに、バスター変数としてリリースハッシュを使用することで、本番リリースごとにキャッシュを無効にすることができます。

これは、dev cachebustingメソッドがを使用してどのように見えるか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

これはChromeの別のオプションです。

ヒットF12して開発者ツールを開きます。次に、[ リソース] > [ キャッシュストレージ] > [ キャッシュの更新]をクリックします。

ここに画像の説明を入力してください

他の回答のようにキャッシュを無効にする必要がないため、このオプションが好きです。


2016年11月のChrome v。54.0.2840.99では、ResourcesではなくApplication.rというタブでこれを見つけました。
StackOverflowUser 2016年

0

ブラウザ/プロキシキャッシュを制御することはできないため、ブラウザ/プロキシキャッシュを防ぐソリューションはありません。

新しいコンテンツをユーザーに強制してHTMLファイルの名前を変更するもう1つの方法!まさにhttps://www.npmjs.com/package/grunt-filerevがアセットに対して行うように。


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.