Keith Neuse
Keith Neuse

Reputation: 723

How to clear template cache?

In Angular 2, how do you clear the template cache? There are tons of answers for Angular 1, but none for 2.

The issue I am having is that when I change the contents of the html pages referenced by templateUrl on any components, the html pages don't change in the browser until I manually navigate to the templateUrl in the browser and hit reload. I know you can disable the browser cache to solve this during development, but my concern is that users can see an outdated html page if they have it cached in their browser when I go to update a website with Angular 2.

Here is a link to the stack overflow questions for Angular 1 AngularJS disable partial caching on dev machine

Below is a snippet and I am having issues with app.html updating when its content is changed.

@Component({
    selector: 'photogallery-app',
    templateUrl: './app/app.html',
    directives: [ROUTER_DIRECTIVES, CORE_DIRECTIVES]
})

Upvotes: 32

Views: 80993

Answers (9)

Abhishek Gautam
Abhishek Gautam

Reputation: 1767

In Angular 5.X we can use the compiler in the same way as 2.0.

Import the compiler:

import { Compiler } from '@angular/core';

Inject the Dependency in your component constructor :

constructor(private _compiler: Compiler) { }

Clear the cache:

this._compiler.clearCache();

Upvotes: 6

Fernando Leal
Fernando Leal

Reputation: 10125

In Angular 2.0.2 we can clear the template cache as follows:

Import:

import { Compiler } from '@angular/core';

Dependency Injector:

constructor(private _compiler: Compiler) {
}

Usage:

this._compiler.clearCache();

Note: I believe that this solution works from Angular 2.0.0 (RTM)

Update

In current versions (4.x) of Angular clearCache() for is no longer working. This has already been reported in the Angular Github (by @Olezt) and possibly will be corrected in the future.

Explanation of functional purpose of clearcache() method:

Another question that is unclear is the functional purpose of the clearCache() method, clearCache() has the responsibility of removing the templateUrl, stylesUrl, etc. specified in @Component. (I use it to discard the view loaded in templateUrl and request a updated view of the server, in my project the view resulting from this request is changed according to exchange user/permissions for example. So the need to discard the one previously loaded.)

clearCache() has no action on the browser cache, or anything beyond the Angular, it only acts on the @Component, @NgModule, etc. Angular caches, nothing more.

Upvotes: 14

G Chen
G Chen

Reputation: 199

I just appended a string to the templateUrl to avoid caching. Here is my solution: https://csjdpw.atlassian.net/wiki/x/gCGWAg

Upvotes: 1

Victor Bredihin
Victor Bredihin

Reputation: 2360

gulpfile.js

var gulp = require('gulp'),
    replace = require('gulp-replace');

    gulp.task('release', function() {
        // cache busting for html
        gulp.src([app/**'])
            .pipe(replace(/\.html.*'/g, '.html?v' + Date.now() + "'"))
            .pipe(gulp.dest('web/app'));

        // cache busting for js
        gulp.src(['main.html'])
            .pipe(replace(/version = (\d+)/g, 'version = ' + Date.now()))
            .pipe(gulp.dest('src/AppBundle/Resources/views'));
    });

main.html

<html>
    <head>
        <script src="{{ asset('js/systemjs.config.js') }}"></script>
        <script>
            var systemLocate = System.locate,
                version = 1477001404442;
            System.locate = function(load) {
                var System = this;

                return Promise.resolve(systemLocate.call(this, load)).then(function(address) {
                    return address + System.cacheBust;
                });
            };
            System.cacheBust = '?v=' + version;

            System.import('app').catch(function(err){ console.error(err); });
        </script>
    </head>
</html>

any-component.ts

@Component({
    selector: 'any-selector',
    templateUrl: '/app/template.html'
})

then just execute gulp release and you are good to go live

Upvotes: 3

James
James

Reputation: 2841

First import the TemplateCompiler.

import { TemplateCompiler } from 'angular2/src/compiler/template_compiler';

Next inject the TemplateCompiler in your constructor.

constructor(private _templateCompiler: TemplateCompiler)

Finally use that to clear the cache. Note this clears all templates.

this._templateCompiler.clearCache();

UPDATE: Angular 2 Beta 17

First import the RuntimeCompiler.

import { RuntimeCompiler} from 'angular2/src/compiler/runtime_compiler';

Next inject the RuntimeCompiler in your constructor.

constructor(private _runtimeCompiler: RuntimeCompiler)

Finally use that to clear the cache. Note this clears all templates.

this._runtimeCompiler.clearCache();

UPDATE: Angular 2 RC 1

First import the RuntimeCompiler.

import { RuntimeCompiler} from '@angular/compiler/src/runtime_compiler';

Next inject the RuntimeCompiler in your constructor.

constructor(private _runtimeCompiler: RuntimeCompiler)

Finally use that to clear the cache. Note this clears all templates.

this._runtimeCompiler.clearCache();

UPDATE: Angular 2 RC 4

First import the RuntimeCompiler.

Notice the path change from RC1. The path listed for RC1 will throw errors when calling .ClearCache() if used with RC4

import { RuntimeCompiler} from '@angular/compiler';

Next inject the RuntimeCompiler in your constructor

constructor(private _runtimeCompiler: RuntimeCompiler)

Finally use that to clear the cache. Note this clears all templates.

this._runtimeCompiler.clearCache();

UPDATE: Angular 2.0.0 (RTM)

It cannot be done. I have an app that serves one set templates for logged in users, and another set for those not logged in. After upgrading to 2.0.0, I can see no way to accomplish the same task. While I try to figure out the best way to re-architect the application, I have resorted to this instead:

location.reload();

That works (but obviously reloads the entire page).

Upvotes: 24

Kaveh Shahbazian
Kaveh Shahbazian

Reputation: 13513

I had a similar question. As a quick hack, i've solved this by introducing a global var in a module like export var fileVersion = '?tmplv=' + Date.now(); - at development time and change it for production - and use it in components like:

@Component({
    selector: 'my-component',
    templateUrl: '/app/templates/my-component.html' + fileVersion,
})

So I have just to refresh the browser to see the changes. In production use export var fileVersion = '?tmplv=v1.3.7yourVersionNumber';.

Upvotes: 2

VahidN
VahidN

Reputation: 19156

A better solution is to bundle all of the required files and produce a single .js file, which can be invalidated very easily using a simple query string at the end of the path (?v=1.x). For more info take a look at this official document: Introduction to Webpack: https://angular.io/docs/ts/latest/guide/webpack.html

Upvotes: 0

Keith Neuse
Keith Neuse

Reputation: 723

The following stack over flow question provides a great strategy for solving this problem by appending a version parameter to the Url.

Force browser to clear cache

This in theory should work great for production releases. Then for development, I can simple disable the browser cache.

Upvotes: 3

james_s_tayler
james_s_tayler

Reputation: 1933

I think the easiest thing to do is open a new session using incognito mode because nothing gets cached so it will always force a reload.

Upvotes: -4

Related Questions