Angular 7 Caching Issues

Asked by At

We have an Angular 7 application and we are using Angular CLI for the build, we build the application with:

ng build --prod

We have checked and the hash is added to the filenames. We have also set index.html with the following:

<meta http-equiv="Cache-control" content="no-cache, no-store, must-revalidate">
<meta http-equiv="Pragma" content="no-cache">

Despite this we are still having to ask our users to ctrl+F5 after a release to see the latest version, it appears Chrome is caching the index.html.

Is there anyway around this, a better way around this. We are considering with each release changing the index.html file to append the current date and time to the name and the angular.json but we would prefer to solve this using the tools provided.

Any help appreciated.

1 Answers

1
Robin Webb On

IIS/Direct Hosting Solution

You could add the "cache busting" to your interceptor if you're using it:

import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler, HttpHeaders } from '@angular/common/http';

@Injectable()
export class CacheInterceptor implements HttpInterceptor {

  intercept(req: HttpRequest<any>, next: HttpHandler) {
    const httpRequest = req.clone({
      headers: new HttpHeaders({
        'Cache-Control': 'no-cache',
        'Pragma': 'no-cache',
        'Expires': 'Sat, 01 Jan 2000 00:00:00 GMT'
      })
    });

    return next.handle(httpRequest);
  }
}

Further details here:

https://medium.com/@tltjr/disabling-internet-explorer-caching-in-your-angular-5-application-3e148f4437ad

Web API/IIS Hoting Solution

If you're using a .Net Core Web API project to host the Angular project then you can add the following lines to your Startup.cs in the public void Configure(IApplicationBuilder app, IHostingEnvironment env) method.

The important lines are:

context.Context.Response.Headers.Add("Cache-Control", "no-cache, no-store, must-revalidate");
context.Context.Response.Headers.Add("Expires", "0");
context.Context.Response.Headers.Add("Pragma", "no-cache");
 public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseHsts();
            }

            app.UseAuthentication();

            app.UseDefaultFiles();

            app.UseStaticFiles(new StaticFileOptions
            {
                OnPrepareResponse = context =>
                {
                    context.Context.Response.Headers.Add("Cache-Control", "no-cache, no-store, must-revalidate");
                    context.Context.Response.Headers.Add("Expires", "0");
                    context.Context.Response.Headers.Add("Pragma", "no-cache");
                }
            });

            app.UseMvc();

            app.MapWhen(x => !x.Request.Path.Value.StartsWith("/api"), builder =>
            {
                builder.Use((context, next) =>
                {
                    context.Request.Path = new PathString("/index.html");
                    return next();
                });

                builder.UseStaticFiles(new StaticFileOptions
                {
                    OnPrepareResponse = context =>
                    {
                        context.Context.Response.Headers.Add("Cache-Control", "no-cache, no-store, must-revalidate");
                        context.Context.Response.Headers.Add("Expires", "0");
                        context.Context.Response.Headers.Add("Pragma", "no-cache");
                    }
                });

            });
        }

We tried various solutions but this was the only "cache busting" solution that worked for us.

Good luck!