caching - clear browser cache angularjs
AngularJS deshabilita el almacenamiento en caché parcial en la máquina de desarrollo (13)
Tengo problemas con el almacenamiento en caché de parciales en AngularJS.
En mi página HTML tengo:
<body>
<div ng-view></div>
<body>
donde se cargan mis parciales.
Cuando cambio el código HTML en mi parcial, el navegador todavía carga datos antiguos.
¿Hay algún trabajo alrededor?
Solución para Firefox (33.1.1) utilizando Firebug (22.0.6)
- Herramientas> Herramientas web> Firebug> Abrir Firebug.
- En las vistas de Firebug vaya a la vista "Red".
- Aparecerá un símbolo de menú desplegable junto a "Red" (título de la vista).
- Seleccione "Desactivar caché del navegador" en el menú desplegable.
Actualizar el documento cada 30 segundos:
<head>
<meta http-equiv="refresh" content="30">
</head>
Aprovechando un poco la respuesta de @ Valentyn, aquí hay una forma de borrar automáticamente la memoria caché siempre que cambie el contenido de ng-view:
myApp.run(function($rootScope, $templateCache) {
$rootScope.$on(''$viewContentLoaded'', function() {
$templateCache.removeAll();
});
});
Como han dicho otros, eliminar el almacenamiento en caché por completo para propósitos de desarrollo puede hacerse fácilmente sin cambiar el código: use una configuración del navegador o un complemento. Fuera de dev, para anular el almacenamiento en caché de la plantilla angular de las plantillas basadas en rutas, elimine la URL de la plantilla de la caché durante $ routeChangeStart (o $ stateChangeStart, para el enrutador UI) como mostró Shayan. Sin embargo, eso NO afecta el almacenamiento en caché de las plantillas cargadas por ng-include, porque esas plantillas no se cargan a través del enrutador.
Quería poder realizar una revisión de cualquier plantilla, incluidas las cargadas por ng-include, en producción y hacer que los usuarios reciban la revisión en su navegador rápidamente, sin tener que volver a cargar toda la página. Tampoco me preocupa derrotar el almacenamiento en caché HTTP de las plantillas. La solución es interceptar cada solicitud HTTP que realiza la aplicación, ignorar aquellas que no son para las plantillas .html de mi aplicación, luego agregar un parámetro a la URL de la plantilla que cambia cada minuto. Tenga en cuenta que la comprobación de ruta es específica a la ruta de las plantillas de su aplicación. Para obtener un intervalo diferente, cambie los cálculos para el parámetro o elimine el% completamente para no tener almacenamiento en caché.
// 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;
}
Como se mencionó en las otras respuestas, here y here , el caché se puede borrar usando:
$templateCache.removeAll();
Sin embargo, como lo sugiere gatoatigrado en el comment , esto solo parece funcionar si la plantilla html se sirvió sin encabezados de caché.
Así que esto funciona para mí:
En angular:
app.run([''$templateCache'', function ( $templateCache ) {
$templateCache.removeAll(); }]);
Puede agregar encabezados de caché de varias maneras, pero aquí hay un par de soluciones que funcionan para mí.
Si usa IIS
, agregue esto a su web.config:
<location path="scripts/app/views">
<system.webServer>
<staticContent>
<clientCache cacheControlMode="DisableCache" />
</staticContent>
</system.webServer>
</location>
Si usa Nginx, puede agregar esto a su configuración:
location ^~ /scripts/app/views/ {
expires -1;
}
Editar
Acabo de darme cuenta de que la pregunta mencionaba la máquina dev
, pero espero que esto todavía pueda ayudar a alguien ...
Descubrí que el método de interceptor HTTP funciona bastante bien y permite flexibilidad y control adicionales. Además, puede almacenar el caché de cada versión de producción utilizando un hash de versión como la variable de buster.
Aquí es cómo se ve el método dev cachebusting usando 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'');
}]);
Este fragmento me ayudó a deshacerme del almacenamiento en caché de plantillas.
app.run(function($rootScope, $templateCache) {
$rootScope.$on(''$routeChangeStart'', function(event, next, current) {
if (typeof(current) !== ''undefined''){
$templateCache.remove(current.templateUrl);
}
});
});
Los detalles del siguiente fragmento de código se pueden encontrar en este enlace: http://oncodesign.io/2014/02/19/safely-prevent-template-caching-in-angularjs/
Estoy publicando esto solo para cubrir todas las posibilidades, ya que ninguna de las otras soluciones funcionó para mí (lanzaron errores debido a las dependencias de la plantilla angular-bootstrap, entre otras).
Mientras desarrolla / depura una plantilla específica, puede asegurarse de que siempre se actualice al incluir una marca de tiempo en la ruta, como esta:
$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();
};
}
});
Observe el final ?nd='' + Date.now()
en la variable templateUrl
.
No existe una solución para evitar el almacenamiento en caché del navegador / proxy ya que no puede tener el control sobre él.
¡La otra forma de forzar contenido nuevo a sus usuarios es renombrar el archivo HTML! Exactamente como https://www.npmjs.com/package/grunt-filerev hace para los activos.
Para Desarrollo, también puede desactivar el caché del navegador - En Chrome Dev Tools en la parte inferior derecha, haga clic en el engranaje y marque la opción
Desactivar caché (mientras DevTools está abierto)
Actualización: en Firefox hay la misma opción en Depurador -> Configuración -> Sección avanzada (verificada para la Versión 33)
Actualización 2: Aunque esta opción aparece en Firefox, algunos informes no funcionan. Sugiero usar Firebug y seguir la respuesta de hadaytullah.
Si está hablando de la memoria caché que se ha utilizado para el almacenamiento en caché de plantillas sin volver a cargar toda la página, entonces puede vaciarla por algo como:
.controller(''mainCtrl'', function($scope, $templateCache) {
$scope.clearCache = function() {
$templateCache.removeAll();
}
});
Y en el marcado:
<button ng-click=''clearCache()''>Clear cache</button>
Y presione este botón para borrar el caché.
Si está utilizando el enrutador UI, puede usar un decorador y actualizar el servicio $ templateFactory y agregar un parámetro de cadena de consulta a templateUrl, y el navegador siempre cargará la nueva plantilla desde el servidor.
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]);
Estoy seguro de que puede lograr el mismo resultado decorando el método "cuándo" en $ routeProvider.