Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 7 Caching Issues

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.

like image 984
user351711 Avatar asked Apr 29 '19 08:04

user351711


People also ask

How do I clear Angular cache?

Angular cache There is no command to clear the cache, just run rm -rf . angular/cache .

How do I stop index html from being cached?

You have to set the Cache-Control header to let the browsers know that they don't have to cache any content for that request. ( Pragma & Cache-Control is one and the same thing but from the different HTTP specification.

What is Max age in Cache-Control?

Cache-control: max-age It is the maximum amount of time specified in the number of seconds. For example, max-age=90 means that a HTTP response remains in the browser as a cached copy for the next 90 seconds before it can be available for reuse.

What is cache busting in Angular?

This entails attaching a unique version identifier to the file, which ensures that a fresh version is fetched, instead of a stale, cached version. In this article, we'll examine two strategies to apply cache busting to our translation files, using Angular and Transloco.


1 Answers

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!

like image 60
Robin Webb Avatar answered Sep 19 '22 22:09

Robin Webb