AngularJS menonaktifkan caching parsial pada mesin dev


210

Saya punya masalah dengan caching parsial di AngularJS.

Di halaman HTML saya, saya punya:

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

di mana sebagian saya dimuat.

Ketika saya mengubah kode HTML di sebagian saya, browser masih memuat data lama.

Apakah ada solusi?


4
Hanya catatan singkat: Saya punya masalah dengan ini yang lebih terkait dengan header kontrol cache aplikasi Flask saya mengirim kembali. Saya mengatasi masalah ini dengan menambahkan app.config.update(SEND_FILE_MAX_AGE_DEFAULT=0)ke flask_app.py. (Saya membayangkan hal serupa ada untuk server web lain).
gatoatigrado

4
Jika Anda menggunakan chrome lakukan a Ctrl+Shift+R(mis. Hard Reload) dan tidak peduli mekanisme caching apa yang digunakan chrome akan mengabaikannya dan mengambil kembali semua skrip, stylesheet dll.
snajahi

4
ctrl + shift + R tidak bekerja untuk saya di Chrome, tetapi pada alat pengembang "jaringan" tab, mengklik "nonaktifkan cache" berfungsi dengan sempurna. Bagi saya, ini adalah masalah sisi klien yang seharusnya tidak diselesaikan menggunakan peretasan di server seperti banyak saran di bawah ini; itu harus diperbaiki pada klien di mana "masalah" ada. Jika Anda memperbaikinya di server, dan lupa untuk membatalkannya, produksi dapat terpengaruh.
Ant Kutschera

8
ctrl + shift + R mem-bypass cache untuk permintaan normal. permintaan ajax dibuat dari sudut untuk ng-include| ng-view| templateUrltidak ditangani oleh pintasan ini
André Werlang

2
Anda tidak dapat meminta semua pengguna akhir untuk Ctrl + Shift + R ketika mengunjungi situs, jadi apa jawaban untuk pertanyaan ini untuk kasus non pengembangan? "Bagi saya, ini adalah masalah sisi klien yang seharusnya tidak diselesaikan dengan menggunakan peretasan pada server seperti banyak saran di bawah ini" - Saya tidak setuju, Anda tidak dapat mengontrol klien di lingkungan web sehingga perbaikan untuk produksi harus digerakkan oleh aplikasi. Untuk alasan itu saya menerima: $ rootScope. $ On ('$ viewContentLoaded', function () {$ templateCache.removeAll ();});
Robert Christian

Jawaban:


200

Untuk Pengembangan, Anda juga dapat menonaktifkan cache browser - Di Alat Dev Chrome di klik kanan bawah roda gigi dan centang opsi

Nonaktifkan cache (saat DevTools terbuka)

Pembaruan: Di Firefox ada opsi yang sama di Debugger -> Pengaturan -> Bagian Lanjutan (diperiksa untuk Versi 33)

Pembaruan 2: Meskipun opsi ini muncul di Firefox, beberapa laporan tidak berfungsi. Saya sarankan menggunakan pembakar dan mengikuti jawaban hadaytullah.


7
Ini seharusnya menjadi jawaban yang diterima karena tidak memerlukan perubahan kode, dan lebih ke titik permintaan OP. Tentu saja Anda ingin aplikasi produksi untuk meng-cache permintaan, sehingga melakukan apa yang disarankan orang-orang di atas, meskipun maknanya baik, bisa terbukti bermasalah jika kode dibiarkan dalam aplikasi produksi.
Aaron Wagner

Adakah saran untuk peramban lain seperti Firefox?
Lereveme

Di Firefox: Debugger> Pengaturan (roda gigi) ada opsi yang sama.
LukeSolar

5
Ini tidak berfungsi di Firefox. Bahkan ketika cache dinonaktifkan, dan kotak alat terbuka, template masih di-cache.
Patrick J Collins

4
Apakah caching juga memengaruhi produksi? Bagaimana jika saya mendorong file web baru ke server, apa yang mencegah permintaan berikutnya dari klien produksi untuk memuat versi cache yang telah diterbitkan sebelumnya?
meffect

111

Membangun sedikit jawaban atas @ Valentyn, inilah salah satu cara untuk selalu membersihkan cache secara otomatis setiap kali konten tampilan-ng berubah:

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

@ user252690 Mungkin juga perlu memastikan templat html tidak dikirim dengan header cache. Lihat di sini dan di sini untuk kemungkinan perbaikan
Chris Foster

30
Sedikit peringatan: Mengosongkan $ templateCache mungkin sebenarnya memiliki konsekuensi yang tidak diinginkan. Sebagai contoh, UI Bootstrap menambahkan parsial default langsung ke $ templateCache selama inisialisasi dan kemudian mengharapkan mereka ada di sana.
Strille

@ Strille Saya mencoba menggunakan Modal angular-ui-bootstrap. Munculan tidak terlihat. karena $ templateCache.removeAll (); ada perbaikan untuk itu?
Mukun

4
@Mukun: Tidak ada cara mudah memperbaiki cara saya melihatnya, selain tidak menggunakan removeAll () tetapi gunakan saja remove () untuk menghapus kunci yang perlu Anda hapus. Anda akan membutuhkan semacam pembukuan untuk mengetahui kunci mana yang harus dihapus.
Strille

apakah ada cara untuk menghapus cache hanya untuk cache tampilan ui tertentu.
Gayan

37

Seperti disebutkan dalam jawaban lain, di sini dan di sini , cache dapat dihapus dengan menggunakan:

$templateCache.removeAll();

Namun seperti yang disarankan oleh gatoatigrado dalam komentar , ini hanya berfungsi jika template html disajikan tanpa header cache.

Jadi ini bekerja untuk saya:

Dalam sudut:

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

Anda mungkin menambahkan header cache dalam berbagai cara tetapi di sini ada beberapa solusi yang cocok untuk saya.

Jika menggunakan IIS, tambahkan ini ke web.config Anda:

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

Jika menggunakan Nginx, Anda dapat menambahkan ini ke konfigurasi Anda:

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

Edit

Saya baru menyadari bahwa devmesin yang disebutkan pertanyaan tetapi semoga ini masih dapat membantu seseorang ...


2
ya, meskipun ini tidak menjawab pertanyaan asli secara langsung, ini ternyata membantu saya memecahkan masalah caching di situs web langsung.
Andre

31

Jika Anda berbicara tentang cache yang digunakan untuk cache template tanpa memuat ulang seluruh halaman, maka Anda dapat mengosongkannya dengan sesuatu seperti:

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

Dan di markup:

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

Dan tekan tombol ini untuk menghapus cache.


22

Solusi Untuk Firefox (33.1.1) menggunakan Firebug (22.0.6)

  1. Tools> Web-Tools> Firebug> Open Firebug.
  2. Dalam tampilan Firebug pergi ke tampilan "Net".
  3. Simbol menu tarik turun akan muncul di sebelah "Net" (judul tampilan).
  4. Pilih "Nonaktifkan Cache Browser" dari menu drop down.

Sudah mencoba Firebug (2.0.11) dan Firefox (38.0.1) di mac tetapi ini tidak berhasil.
paullb

19

Cuplikan ini membantu saya menyingkirkan caching template

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

Detail cuplikan berikut dapat ditemukan di tautan ini: http://oncodesign.io/2014/02/19/safely-prevent-template-caching-in-angularjs/


nitpick tetapi kapan saat ini tidak pernah menjadi objek? Tidak yakin juga tidak pernah ada di sana kecualiif (!current) { return; }
Nate-Wilkins

Ini mengalahkan caching Angular tentang templat berbasis rute, tetapi tidak mencakup sebagian.
bradw2k

16

Saya memposting ini hanya untuk menutup semua kemungkinan karena tidak ada solusi lain yang bekerja untuk saya (mereka melemparkan kesalahan karena dependensi templat angular-bootstrap, antara lain).

Saat Anda mengembangkan / men-debug templat tertentu, Anda dapat memastikannya selalu menyegarkan dengan menyertakan stempel waktu di jalur, seperti ini:

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

Perhatikan final ?nd=' + Date.now()dalam templateUrlvariabel.


1
Kemudian Anda dapat mengatur .value('DEBUG', true)untuk mengaktifkan garis itu atau tidak.
diosney

1
Solusi saya adalah menggunakan berikut ini dalam tahap inisialisasi modul utama saya di bawah .run(function($rootScope) { $rootScope.DEBUG = true; ...dan kemudian dalam direktif menyuntikkan yang $ rootScope seperti .directive('filter', ['$rootScope', function($rootScope)...dan objek-properti kembali: templateUrl: '/app/components/filter/filter-template.html' + ($rootScope.DEBUG ? '?n=' + Date.now() : ''). Mungkin Anda bisa menguraikan pendekatan .value ('DEBUG' Anda, benar)? Terpilih!
JackLeEmmerdeur

Penggunaannya .value('DEBUG', truesama seperti yang Anda lakukan dengan $rootScope, tetapi tanpa mengacaukannya :) Anda kemudian dapat menyuntikkan DEBUGke controller dan permintaan sebagai layanan normal.
diosney

Bisakah Anda memperpanjang kode sumber dalam jawaban Anda untuk memasukkan hal itu .value(...), jika itu tidak terlalu canggih? Saya kira konsep di belakang adalah praktik terbaik sudut yang tidak saya ketahui.
JackLeEmmerdeur

1
Solusi ini sangat berguna ketika bekerja dengan Ionic. Ini akan menghemat banyak waktu saya karena membuat isi hati berguna lagi. Terima kasih banyak!
ajuser

11

Seperti yang orang lain katakan, mengalahkan caching sepenuhnya untuk tujuan dev dapat dilakukan dengan mudah tanpa mengubah kode: gunakan pengaturan browser atau plugin. Di luar dev, untuk mengalahkan cache template Sudut dari template berbasis rute, hapus URL template dari cache selama $ routeChangeStart (atau $ stateChangeStart, untuk Router UI) seperti yang ditunjukkan Shayan. Namun, itu TIDAK mempengaruhi cache template yang dimuat oleh ng-include, karena template itu tidak dimuat melalui router.

Saya ingin dapat memperbaiki hotfix semua templat, termasuk yang dimuat oleh ng-include, dalam produksi dan membuat pengguna menerima hotfix di browser mereka dengan cepat, tanpa harus memuat ulang seluruh halaman. Saya juga tidak khawatir tentang mengalahkan cache HTTP untuk templat. Solusinya adalah dengan mencegat setiap permintaan HTTP yang dibuat aplikasi, abaikan permintaan yang bukan untuk templat .html aplikasi saya, lalu tambahkan param ke URL templat yang berubah setiap menit. Perhatikan bahwa pemeriksaan jalur khusus untuk jalur templat aplikasi Anda. Untuk mendapatkan interval yang berbeda, ubah matematika untuk param, atau hapus% sepenuhnya untuk tidak mendapatkan caching.

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

Saya tertarik dengan solusi Anda - apakah Anda menyimpan kode ini untuk selamanya - atau untuk jangka waktu tertentu setelah Anda melakukan perubahan? Alasan - akan peduli tentang kinerja. Juga, Anda menyebutkan efek samping mengalahkan HTTP. Maksud Anda itu adalah efek samping yang baik, benar - artinya itulah yang Anda maksudkan untuk mendapatkan 'perbaikan terbaru'? Thx
jamie

1
Saya meninggalkan kode ini untuk selamanya, meskipun kami memutar kembali panjang cache-busting menjadi 10 menit. Jadi, setiap 10 menit penggunaan, pengguna akan memuat ulang template html baru. Untuk aplikasi bisnis saya yang merupakan biaya yang dapat diterima untuk mendapatkan kemampuan templat templat panas, tapi jelas itu akan mengganggu kinerja terlalu banyak untuk beberapa jenis aplikasi. ... Sangat disayangkan bahwa cache HTTP dikalahkan juga, tapi saya tidak melihat cara untuk secara cerdas mengalahkan cache template Angular tanpa mengalahkan etag dll juga. Caching template Angular IMO tidak cukup dapat dikonfigurasi.
bradw2k

1
+1 Saya punya ide yang sama, tetapi saya hanya memotong untuk localhost. Anda dapat melihat implementasi pencegat saya di sini: overengineer.net/...
joshcomley

@ joshcomley Jika Anda hanya perlu mengalahkan caching di localhost, mengapa tidak menggunakan plugin browser yang mengalahkan semua caching?
bradw2k

@ bradw2k dengan cara ini saya memegang kendali penuh atas apa yang ada dan tidak di-cache, yang dapat berguna untuk pengembangan. Saya juga menguji di semua browser, dan tidak semua browser memiliki ekstensi yang melakukan apa yang saya butuhkan. Saya juga dapat memiliki indikator di situs dalam pengembangan yang memberitahu saya apakah caching dinonaktifkan atau tidak, karena kadang-kadang saya hanya ingin menonaktifkan dan menguji di seluruh browser untuk sementara waktu.
joshcomley

8

Jika Anda menggunakan router UI maka Anda dapat menggunakan dekorator dan memperbarui layanan $ templateFactory dan menambahkan parameter string kueri ke templateUrl, dan browser akan selalu memuat template baru dari server.

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

Saya yakin Anda dapat mencapai hasil yang sama dengan mendekorasi metode "kapan" di $ routeProvider.


Alternatif yang jauh lebih baik adalah dengan menggunakan plugin seperti gulp-angular-templatecache untuk mendaftarkan templat js sudut di $ templateCache. Ini harus digunakan bersama dengan gulp-rev. Setiap kali perubahan template, file JavaScript baru dengan nomor revisi yang berbeda akan dibuat dan caching tidak akan pernah menjadi masalah.
Aman Mahajan

3

Saya menemukan bahwa metode interseptor HTTP berfungsi dengan baik, dan memungkinkan fleksibilitas & kontrol tambahan. Selain itu, Anda dapat cache-bust untuk setiap rilis produksi dengan menggunakan hash rilis sebagai variabel buster.

Berikut adalah bagaimana metode cachebusting dev terlihat seperti menggunakan 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

Berikut adalah opsi lain di Chrome.

Hit F12untuk membuka alat pengembang. Lalu Sumber Daya > Penyimpanan Tembolok > Segarkan Ulang Tembolok .

masukkan deskripsi gambar di sini

Saya suka opsi ini karena saya tidak harus menonaktifkan cache seperti pada jawaban lain.


Di Chrome v. 54.0.2840.99 pada November 2016 saya menemukan ini di tab bernama Application.rather daripada Resources.
StackOverflowUser


Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.