AngularJS отключить частичное кэширование на компьютере разработчика

205

У меня проблема с частицами кеширования в AngularJS.

На моей странице HTML у меня есть:

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

где мои частичные файлы загружены.

Когда я меняю HTML-код в своем частичном, браузер все еще загружает старые данные.

Есть ли способ обхода?

  • 4
    Просто небольшое замечание: у меня была проблема с этим, которая была больше связана с заголовками контроля кэша, которые отправляло мое приложение Flask. Я app.config.update(SEND_FILE_MAX_AGE_DEFAULT=0) эту проблему, добавив app.config.update(SEND_FILE_MAX_AGE_DEFAULT=0) в мой flask_app.py . (Я думаю, что подобные вещи существуют для других веб-серверов).
  • 4
    Если вы используете Chrome, просто нажмите Ctrl+Shift+R (т.е. Hard Reload), и независимо от того, какой механизм кэширования используется, Chrome проигнорирует его и повторно загрузит все скрипты, таблицы стилей и т. Д.
Показать ещё 3 комментария
Теги:
caching
browser-cache

13 ответов

205
Лучший ответ

Для разработки вы также можете деактивировать кеш браузера. В Chrome Dev Tools в правом нижнем правом углу нажмите на передачу и отметьте опцию

Отключить кеш (пока DevTools открыт)

Обновление: в Firefox есть такая же опция в Debugger → Settings → Advanced Section (проверена для версии 33)

Обновление 2: Хотя эта опция появляется в Firefox, некоторые отчеты не работают. Я предлагаю использовать firebug и после ответа hadaytullah.

  • 7
    Это должен быть принятый ответ, потому что он не требует смены кода и более важен для запроса ОП. Конечно, вы бы хотели, чтобы производственное приложение кешировало запросы, поэтому выполнение того, что предложили вышеупомянутые люди, хотя и имеет смысл, может оказаться проблематичным, если оставить код в производственном приложении.
  • 0
    Это хороший ответ для меня. Это простой способ отключить кеш во время разработки. Спасибо!
Показать ещё 9 комментариев
114

Основываясь на @Valentyn, ответьте немного, здесь один способ всегда автоматически очищать кеш при изменении содержимого ng-view:

myApp.run(function($rootScope, $templateCache) {
   $rootScope.$on('$viewContentLoaded', function() {
      $templateCache.removeAll();
   });
});
  • 40
    Выглядит многообещающе, только не работает.
  • 0
    @ user252690 Вероятно, также необходимо убедиться, что HTML-шаблон не был отправлен с заголовками кэша. Смотрите здесь и здесь для возможных исправлений
Показать ещё 5 комментариев
35

Как уже упоминалось в других ответах, здесь и здесь, кеш можно очистить, используя:

$templateCache.removeAll();

Однако, как было предложено gatoatigrado в comment, это только работает, если шаблон html был отправлен без заголовков кеша.

Итак, это работает для меня:

В angular:

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

Edit

Я только понял, что вопрос, упомянутый dev машиной, но, надеюсь, это может помочь кому-то...

  • 2
    да, хотя это не дает прямого ответа на первоначальный вопрос, это действительно помогло мне решить проблему кеширования на живом веб-сайте.
31

Если вы говорите о кеше, который был использован для кэширования шаблонов без перезагрузки всей страницы, вы можете его очистить чем-то вроде:

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

И в разметке:

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

И нажмите эту кнопку, чтобы очистить кеш.

22

Решение для Firefox (33.1.1) с использованием Firebug (22.0.6)

  • Инструменты > Веб-инструменты > Firebug > Open Firebug.
  • В представлениях Firebug перейдите в представление "Net".
  • Рядом с "Net" (название представления) появится значок выпадающего меню.
  • Выберите "Отключить кеш браузера" в раскрывающемся меню.
  • 0
    Пробовал на Firebug (2.0.11) и Firefox (38.0.1) на Mac, но это не сработало.
18

Этот фрагмент помог мне избавиться от кэширования шаблонов

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/

  • 0
    Ниппик, но когда ток вообще не объект? Не уверен, что его там тоже нет, но if (!current) { return; }
  • 0
    Это побеждает кеширование Angular шаблонов на основе маршрутов, но не партиций ng-include'd.
Показать ещё 1 комментарий
15

Я публикую это только для того, чтобы охватить все возможности, так как ни один из других решений не работал у меня (они бросили ошибки из-за зависимостей шаблона angular -bootstrap, среди прочего).

Пока вы разрабатываете/отлаживаете определенный шаблон, вы можете убедиться, что он всегда обновляется, включая метку времени в пути, например:

       $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) чтобы включить эту строку или нет.
  • 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», правда)?
Показать ещё 6 комментариев
10

Как говорили другие, полное уничтожение кэширования для целей dev может быть легко выполнено без изменения кода: используйте настройку браузера или плагин. Вне dev, чтобы победить Angular кэширование шаблонов шаблонов на основе маршрутов, удалите URL-адрес шаблона из кэша во время $routeChangeStart (или $StateChangeStart, для UI Router), как показал Шаян. Однако это НЕ влияет на кэширование шаблонов, загруженных ng-include, потому что эти шаблоны не загружаются через маршрутизатор.

Я хотел бы иметь возможность исправлять любой шаблон, включая те, которые были загружены ng-include, в процессе производства, и пользователи быстро получают исправление в своем браузере, не перезагружая всю страницу. Я также не заинтересован в том, чтобы победить HTTP-кеширование для шаблонов. Решение состоит в том, чтобы перехватывать каждый HTTP-запрос, который делает приложение, игнорировать те, которые не подходят для моих шаблонов .html приложения, а затем добавлять параметр к URL-адресу шаблона, который меняется каждую минуту. Обратите внимание, что проверка пути специфична для пути к вашим шаблонам приложений. Чтобы получить другой интервал, измените математику для параметра или полностью удалите%, чтобы не получить кеширование.

// this defeats Angular $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 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;
    }
  • 0
    Меня интересует ваше решение - сохраняете ли вы этот код навсегда или в течение определенного периода времени после внесения изменений? Причина - будет беспокоиться о производительности. Кроме того, вы упоминаете побочный эффект побеждает HTTP. Вы имеете в виду, что это хороший способ побочных эффектов, то есть, это то, что вы хотели, чтобы иметь «исправление»?
  • 1
    Я оставляю этот код навсегда, хотя мы сократили продолжительность очистки кеша до 10 минут. Таким образом, каждые 10 минут использования пользователь будет перезагружать свежие HTML-шаблоны. Для моего бизнес-приложения это приемлемая цена за приобретение возможности оперативного обновления шаблонов, но, очевидно, это слишком сильно ухудшит производительность для некоторых типов приложений. ... К сожалению, HTTP-кеширование также побеждено, но я не вижу способа разумно победить кеширование шаблонов Angular без победы над etag и т. Д. Кэширование шаблонов IMO Angular просто недостаточно настраиваемо.
Показать ещё 5 комментариев
6

Если вы используете 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.

  • 0
    Гораздо лучшая альтернатива - использовать плагин, такой как gulp-angular-templatecache, для регистрации угловых js-шаблонов в $ templateCache. Это следует использовать вместе с gulp-rev. Каждый раз, когда шаблон изменяется, создается новый файл JavaScript с другим номером ревизии, и кеширование никогда не будет проблемой.
2

Я обнаружил, что метод перехватчика HTTP работает очень красиво, и обеспечивает дополнительную гибкость и контроль. Кроме того, вы можете использовать кеш-память для каждой производственной версии, используя хеш-релиз в качестве переменной-бустера.

Вот как выглядит метод кэширования dev, используя 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');
}]);
0

Вот еще один вариант в Chrome.

Нажмите F12, чтобы открыть инструменты разработчика. Затем Ресурсы > Хранение кэша > Обновить кеши.

Изображение 3688

Мне нравится эта опция, потому что мне не нужно отключать кеш, как в других ответах.

  • 0
    В Chrome v. 54.0.2840.99 в ноябре 2016 года я обнаружил это на вкладке «Приложение», а не «Ресурсы».
0

Нет никакого решения предотвратить кеширование браузера/прокси, поскольку вы не можете управлять им.

Другой способ заставить свежий контент вашим пользователям переименовать HTML файл! Точно как https://www.npmjs.com/package/grunt-filerev для активов.

-1

Обновить документ каждые 30 секунд:

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

w3schools HTML-атрибут http-equiv

Ещё вопросы

Сообщество Overcoder
Наверх
Меню