AngularJS vô hiệu hóa bộ nhớ đệm một phần trên máy dev


210

Tôi có vấn đề với các bộ nhớ đệm trong AngularJS.

Trong trang HTML của tôi, tôi có:

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

nơi các phần của tôi được tải.

Khi tôi thay đổi mã HTML một phần, trình duyệt vẫn tải dữ liệu cũ.

Có bất kỳ công việc xung quanh?


4
Chỉ là một ghi chú nhanh: Tôi gặp vấn đề với điều này liên quan nhiều hơn đến các tiêu đề kiểm soát bộ đệm mà ứng dụng Flask của tôi đã gửi lại. Tôi đã khắc phục vấn đề bằng cách thêm app.config.update(SEND_FILE_MAX_AGE_DEFAULT=0)vào flask_app.py. (Tôi tưởng tượng những điều tương tự tồn tại cho các máy chủ web khác).
gatoatigrado

4
Nếu bạn đang sử dụng chrome, chỉ cần thực hiện Ctrl+Shift+R(tức là Tải lại cứng) và cho dù sử dụng cơ chế bộ đệm nào, chrome sẽ bỏ qua nó và tìm nạp lại tất cả các tập lệnh, biểu định kiểu, v.v.
snajahi

4
ctrl + shift + R không hoạt động với tôi trong Chrome, nhưng trên tab "mạng" của công cụ dành cho nhà phát triển, nhấp vào "tắt bộ đệm" hoạt động hoàn hảo. Đối với tôi, đây là vấn đề phía máy khách không nên giải quyết bằng cách sử dụng hack trên máy chủ như nhiều đề xuất dưới đây; nó nên được sửa trên máy khách nơi "vấn đề" tồn tại. Nếu bạn sửa nó trên máy chủ và quên không sửa nó, việc sản xuất có thể bị ảnh hưởng xấu.
Ant Kutschera

8
ctrl + shift + R bỏ qua bộ đệm cho các yêu cầu bình thường. yêu cầu ajax được thực hiện từ góc cho ng-include| ng-view| templateUrlkhông được xử lý bằng phím tắt này
André Werlang

2
Bạn không thể yêu cầu tất cả người dùng cuối sử dụng Ctrl + Shift + R khi truy cập trang web, vậy câu trả lời cho câu hỏi này cho trường hợp không phát triển là gì? "Đối với tôi, đây là sự cố phía máy khách không nên giải quyết bằng cách sử dụng hack trên máy chủ như nhiều đề xuất bên dưới" - Tôi không đồng ý, bạn không thể kiểm soát khách hàng trong môi trường web để khắc phục sự cố sản xuất phải được điều khiển ứng dụng. Vì lý do đó, tôi đã chấp nhận: $ rootScope. $ On ('$ viewContentLoaded', function () {$ templateCache.remove ALL ();});
Robert Christian

Câu trả lời:


200

Để phát triển, bạn cũng có thể tắt bộ đệm của trình duyệt - Trong Chrome Dev Tools ở dưới cùng, nhấp chuột phải vào thiết bị và đánh dấu tùy chọn

Vô hiệu hóa bộ đệm (trong khi DevTools đang mở)

Cập nhật: Trong Firefox có cùng tùy chọn trong Trình gỡ lỗi -> Cài đặt -> Phần nâng cao (đã chọn cho Phiên bản 33)

Cập nhật 2: Mặc dù tùy chọn này xuất hiện trong Firefox nhưng một số báo cáo không hoạt động. Tôi đề nghị sử dụng fireorms và làm theo câu trả lời của hadaytullah.


7
Đây phải là câu trả lời được chấp nhận vì nó không yêu cầu thay đổi mã, và nhiều hơn theo yêu cầu của OP. Tất nhiên, bạn sẽ muốn một ứng dụng sản xuất lưu trữ các yêu cầu bộ đệm, do đó, việc thực hiện những gì những người ở trên gợi ý, trong khi ý nghĩa tốt, có thể chứng minh có vấn đề nếu mã được để lại trong ứng dụng sản xuất.
Aaron Wagner

Bất kỳ đề xuất cho các trình duyệt khác như Firefox?
Lereveme

Trong Firefox: Debugger> Settings (bánh răng) có cùng tùy chọn.
LukeSolar

5
Điều này không hoạt động trong Firefox. Ngay cả khi bộ đệm bị vô hiệu hóa và hộp công cụ được mở, các mẫu vẫn được lưu vào bộ đệm.
Patrick J Collins

4
Liệu bộ nhớ đệm cũng ảnh hưởng đến sản xuất? Điều gì xảy ra nếu tôi đẩy các tệp web mới đến máy chủ, điều gì ngăn các yêu cầu tiếp theo từ các máy khách sản xuất tải các phiên bản được lưu trước đó?
tham gia

111

Dựa trên câu trả lời của @ Valentyn một chút, đây là một cách để luôn tự động xóa bộ đệm bất cứ khi nào nội dung ng-view thay đổi:

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

@ user252690 Có lẽ cũng cần đảm bảo mẫu html không được gửi với các tiêu đề bộ đệm. Xem ở đâyở đây để sửa lỗi có thể
Chris Foster

30
Một chút cảnh báo: Làm trống $ templateCache thực sự có thể có những hậu quả không lường trước được. Chẳng hạn, UI Bootstrap thêm các phần mặc định trực tiếp vào $ templateCache trong quá trình khởi tạo và sau đó hy vọng chúng sẽ ở đó.
Strille

@Strille Tôi đã thử sử dụng Modal angular-ui-bootstrap. Cửa sổ bật lên không nhìn thấy được. bởi vì $ templateCache.remove ALL (); Bất kỳ sửa chữa cho nó?
Mukun

4
@Mukun: Không có cách khắc phục dễ dàng theo cách tôi nhìn thấy, ngoài việc không sử dụng removeAll () mà thay vào đó chỉ sử dụng remove () để xóa các phím bạn cần xóa. Bạn sẽ cần một số loại sổ sách kế toán để biết những phím cần xóa.
Strille

Có cách nào để xóa bộ đệm chỉ cho bộ đệm xem ui cụ thể.
Gayan

37

Như đã đề cập trong các câu trả lời khác, tại đâyđây , bộ đệm có thể được xóa bằng cách sử dụng:

$templateCache.removeAll();

Tuy nhiên, như được đề xuất bởi gatoatigrado trong bình luận , điều này chỉ xuất hiện để hoạt động nếu mẫu html được phục vụ mà không có bất kỳ tiêu đề bộ đệm nào.

Vì vậy, điều này làm việc cho tôi:

Trong góc:

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

Bạn có thể thêm các tiêu đề bộ đệm theo nhiều cách khác nhau nhưng đây là một vài giải pháp phù hợp với tôi.

Nếu sử dụng IIS, hãy thêm phần này vào web.config:

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

Nếu sử dụng Nginx, bạn có thể thêm phần này vào cấu hình của mình:

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

Biên tập

Tôi mới nhận ra rằng câu hỏi đã đề cập đến devmáy nhưng hy vọng điều này vẫn có thể giúp ai đó ...


2
có, mặc dù điều này không trả lời trực tiếp câu hỏi ban đầu nhưng thực tế nó đã giúp tôi giải quyết vấn đề bộ đệm trên một trang web trực tiếp.
Andre

31

Nếu bạn đang nói về bộ đệm được sử dụng để lưu bộ đệm của các mẫu mà không tải lại toàn bộ trang, thì bạn có thể làm trống nó bằng một cái gì đó như:

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

Và trong đánh dấu:

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

Và nhấn nút này để xóa bộ nhớ cache.


22

Giải pháp cho Firefox (33.1.1) bằng cách sử dụng Fireorms (22.0.6)

  1. Công cụ> Công cụ web> Bọ lửa> Mở Bọ lửa.
  2. Trong chế độ xem Firebird, hãy chuyển đến chế độ xem "Net".
  3. Biểu tượng menu thả xuống sẽ xuất hiện bên cạnh "Net" (tiêu đề của chế độ xem).
  4. Chọn "Vô hiệu hóa bộ đệm của trình duyệt" từ menu thả xuống.

Đã thử trên Fireorms (2.0.11) và Firefox (38.0.1) trên mac nhưng điều này không hoạt động.
paullb

19

Đoạn mã này đã giúp tôi thoát khỏi bộ nhớ đệm mẫu

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

Các chi tiết của đoạn trích sau có thể được tìm thấy trên liên kết này: http://oncodesign.io/2014/02/19/safely-prevent-template-caching-in-angularjs/


nitpick nhưng khi nào thì hiện tại không phải là một đối tượng? Không chắc là nó cũng không ở đó nhưngif (!current) { return; }
Nate-Wilkins

Điều này đánh bại bộ nhớ đệm của Angular đối với các mẫu dựa trên tuyến đường, nhưng không phải là các phần của ng.
bradw2k

16

Tôi đang đăng bài này chỉ để đề cập đến tất cả các khả năng vì cả hai giải pháp khác đều không phù hợp với tôi (họ đã ném lỗi do phụ thuộc vào mẫu angst-bootstrap, trong số các giải pháp khác).

Trong khi bạn đang phát triển / gỡ lỗi một mẫu cụ thể, bạn có thể đảm bảo nó luôn được làm mới bằng cách đưa dấu thời gian vào đường dẫn, như sau:

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

Lưu ý cuối cùng ?nd=' + Date.now()trong templateUrlbiến.


1
Sau này bạn có thể thiết lập .value('DEBUG', true)để kích hoạt dòng đó hay không.
diosney

1
Giải pháp của tôi là sử dụng các bước sau trong giai đoạn khởi tạo của mô-đun chính của tôi .run(function($rootScope) { $rootScope.DEBUG = true; ...và sau đó trong lệnh chỉ thị $ rootScope như .directive('filter', ['$rootScope', function($rootScope)...và trong thuộc tính đối tượng được trả về : templateUrl: '/app/components/filter/filter-template.html' + ($rootScope.DEBUG ? '?n=' + Date.now() : ''). Có lẽ bạn có thể xây dựng cách tiếp cận .value ('DEBUG', true) của mình? Nâng cao!
JackLeEmmerdeur

Việc sử dụng .value('DEBUG', truegiống như bạn đã làm với $rootScope, nhưng không làm lộn xộn nó :) Sau này bạn có thể đưa DEBUGvào bộ điều khiển và truy vấn như một dịch vụ bình thường.
diosney

Bạn có thể mở rộng mã nguồn trong câu trả lời của bạn để bao gồm điều hay không .value(...), nếu nó không quá phức tạp? Tôi cho rằng khái niệm đằng sau là một thực tiễn tốt nhất góc cạnh mà tôi không biết.
JackLeEmmerdeur

1
Giải pháp này rất hữu ích khi làm việc với Ionic. Nó sẽ giúp tôi tiết kiệm rất nhiều thời gian vì nó giúp tải lại gan trở nên hữu ích. Cảm ơn rất nhiều!
ajuser

11

Như những người khác đã nói, việc đánh bại hoàn toàn bộ nhớ đệm cho mục đích dev có thể được thực hiện dễ dàng mà không cần thay đổi mã: sử dụng cài đặt trình duyệt hoặc plugin. Bên ngoài dev, để đánh bại bộ nhớ đệm mẫu Angular của các mẫu dựa trên tuyến đường, hãy xóa URL mẫu khỏi bộ đệm trong $ routeChangeStart (hoặc $ stateChangeStart, cho Bộ định tuyến UI) như Shayan đã hiển thị. Tuy nhiên, điều đó KHÔNG ảnh hưởng đến bộ nhớ đệm của các mẫu được tải bởi ng-include, vì các mẫu đó không được tải qua bộ định tuyến.

Tôi muốn có thể hotfix bất kỳ mẫu nào, kể cả những mẫu được tải bởi ng-include, trong sản xuất và để người dùng nhanh chóng nhận được hotfix trong trình duyệt của họ mà không phải tải lại toàn bộ trang. Tôi cũng không quan tâm đến việc đánh bại bộ nhớ đệm HTTP cho các mẫu. Giải pháp là chặn mọi yêu cầu HTTP mà ứng dụng đưa ra, bỏ qua những yêu cầu không dành cho các mẫu .html của ứng dụng của tôi, sau đó thêm một thông số vào URL của mẫu thay đổi mỗi phút. Lưu ý rằng việc kiểm tra đường dẫn là dành riêng cho đường dẫn của các mẫu ứng dụng của bạn. Để có một khoảng khác nhau, hãy thay đổi toán học cho param hoặc xóa hoàn toàn% để không lưu vào bộ đệm.

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

Tôi quan tâm đến giải pháp của bạn - bạn có giữ mã này mãi mãi không - hoặc trong một khoảng thời gian nhất định sau khi bạn thực hiện thay đổi? Lý do - sẽ quan tâm đến hiệu suất. Ngoài ra, bạn đề cập đến hiệu ứng phụ đánh bại HTTP. Ý bạn là đó là một cách hiệu quả phụ đúng - nghĩa là đó là những gì bạn dự định để có 'hotfix'? Thx
jamie

1
Tôi để lại mã này cho tốt, mặc dù chúng tôi đã quay lại thời lượng của bộ nhớ cache đến 10 phút. Vì vậy, cứ sau 10 phút sử dụng, một người dùng sẽ tải lại các mẫu html mới. Đối với ứng dụng biz của tôi, đó là một chi phí chấp nhận được để có được khả năng vá các mẫu nóng, nhưng rõ ràng nó sẽ làm giảm hiệu suất quá nhiều đối với một số loại ứng dụng. ... Thật không may là bộ nhớ đệm HTTP cũng bị đánh bại, nhưng tôi không thấy cách nào để đánh bại bộ nhớ cache mẫu Angular một cách thông minh mà không đánh bại cả v.v. IMO Bộ nhớ đệm mẫu góc không đủ cấu hình.
bradw2k

1
+1 Tôi có cùng ý tưởng, nhưng tôi chỉ chặn cho localhost. Bạn có thể thấy việc triển khai thiết bị đánh chặn của tôi ở đây: overengineer.net/
Kẻ

@joshcomley Nếu bạn chỉ cần đánh bại bộ nhớ đệm trên localhost, tại sao không sử dụng plugin trình duyệt đánh bại tất cả bộ nhớ đệm?
bradw2k

@ bradw2k theo cách này tôi hoàn toàn kiểm soát những gì được và không được lưu trong bộ nhớ cache, có thể hữu ích cho sự phát triển. Tôi cũng thử nghiệm trong tất cả các trình duyệt và không phải tất cả các trình duyệt đều có tiện ích mở rộng làm những gì tôi cần. Tôi cũng có thể có một chỉ báo trên trang web đang phát triển cho tôi biết liệu bộ nhớ đệm có bị vô hiệu hóa hay không, vì đôi khi tôi chỉ muốn tắt và kiểm tra trên các trình duyệt trong một thời gian.
joshcomley

8

Nếu bạn đang sử dụng bộ định tuyến UI thì bạn có thể sử dụng trình trang trí và cập nhật dịch vụ $ templateFactory và nối thêm tham số chuỗi truy vấn vào templateUrl và trình duyệt sẽ luôn tải mẫu mới từ máy chủ.

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

Tôi chắc chắn rằng bạn có thể đạt được kết quả tương tự bằng cách trang trí phương thức "khi" trong $ routeProvider.


Một cách khác tốt hơn là sử dụng một plugin như gulp-angular-templatecache để đăng ký các mẫu js góc trong $ templateCache. Điều này nên được sử dụng cùng với gulp-rev. Mỗi khi mẫu thay đổi, một tệp JavaScript mới có số sửa đổi khác nhau sẽ được tạo và bộ đệm sẽ không bao giờ là vấn đề.
Aman Mahajan

3

Tôi thấy rằng phương thức chặn HTTP hoạt động khá độc đáo và cho phép kiểm soát và linh hoạt bổ sung. Ngoài ra, bạn có thể lưu trữ bộ đệm cho mỗi bản phát hành sản xuất bằng cách sử dụng hàm băm phát hành làm biến buster.

Đây là những gì phương pháp dev cacheebusting trông giống như sử dụng 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

Đây là một tùy chọn khác trong Chrome.

Nhấn F12để mở công cụ phát triển. Sau đó Tài nguyên > Bộ nhớ cache > Làm mới bộ nhớ cache .

nhập mô tả hình ảnh ở đây

Tôi thích tùy chọn này vì tôi không phải tắt bộ đệm như trong các câu trả lời khác.


Trong Chrome v. 54.0.2840.99 vào tháng 11 năm 2016, tôi đã tìm thấy điều này trên một tab có tên Application.rather hơn Tài nguyên.
StackOverflowUser

0

Không có giải pháp nào để ngăn chặn bộ nhớ cache của trình duyệt / proxy vì bạn không thể kiểm soát nó.

Một cách khác để buộc nội dung mới cho người dùng của bạn là đổi tên tệp HTML! Chính xác như https://www.npmjs.com/package/grunt-filerev làm cho tài sản.


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.