12

Everytime I make any change to the index.html with my Angular project, Service Worker never gets updated and always serves the old cached version on index.html. How do I fix this (Also, there is no caching at the server end as well as browser)

Here is my ngsw-config file:

    {
      "index": "/index.html",
      "assetGroups": [{
        "name": "app",
        "installMode": "prefetch",
        "resources": {
          "files": [
            "/favicon.ico",
            "/index.html",
            "/manifest.json"
          ],
          "versionedFiles": [
            "/*.bundle.css",
            "/*.bundle.js",
            "/*.chunk.js"
          ]
        }
      }, {
        "name": "assets",
        "installMode": "lazy",
        "updateMode": "prefetch",
        "resources": {
          "files": [
            "/assets/**"
          ]
        }
      }]
    }

My response headers for the request:

Screenshot of my request to my angular APP

Any idea how to get this fixed?

Thanks

NeNaD
  • 18,172
  • 8
  • 47
  • 89
Sampat
  • 1,301
  • 6
  • 20
  • 34
  • Did you find a solution for this problem ? I'm having a similar issue on a project running Angular 7 and service worker. Somehow, even after I update the cache, when browsing again, the worker sometimes still load an old page (even if it previously showed the new page) – lkartono Jul 22 '19 at 23:49

2 Answers2

5

I think the problem is in the ngsw-config. The .css and .js entries under versionedFiles may not match the .css and .js files in the dist folder if they don't have .bundle or .chunk in their names. In more recent versions of Angular those entries were replaced with "/*.js" and "/*.css", and the files in the dist folder don't have .bundle or .chunk when building for production.

So, the problem actually is that the .js and .css files are not being cached and whenever the files on the server are updated, the app no longer finds them and the browser throws an error (because it returns the index.html) before the service worker can load the "cached" files, detect the changes and update the files.

In Angular 6, versionedFiles behaves the same as files and was deprecated. So, your ngsw-config.json should look like this:

{
  "index": "/index.html",
  "assetGroups": [{
    "name": "app",
    "installMode": "prefetch",
    "resources": {
      "files": [
        "/favicon.ico",
        "/index.html",
        "/manifest.json",
        "/*.css",
        "/*.js"
      ]
    }
  }, {
    "name": "assets",
    "installMode": "lazy",
    "updateMode": "prefetch",
    "resources": {
      "files": [
        "/assets/**"
      ]
    }
  }]
}
danplaza
  • 51
  • 1
  • 4
  • This is the solution that worked for me, with an older Angular app with a service worker for a progressive web app (PWA) who upgraded to later versions of Angular. You might be affected by this error if you are getting errors like `Refused to execute script from 'https://example.com/main.XXXXXXXXXXXXXXX.js' because its MIME type ('text/html') is not executable, and strict MIME type checking is enabled.` – jamesjansson Nov 09 '19 at 13:56
3

You can force the service worker to delete all previous SW caches (index.html too) with a code like this in the service worker:

const DIRTY_CACHE = 'application-version-number-or-whatever';

self.addEventListener('install', () => { 
  // Skip over the "waiting" lifecycle state, to ensure that our 
  // new service worker is activated immediately, even if there's 
  // another tab open controlled by our older service worker code. 
  self.skipWaiting(); 
});

self.addEventListener('activate', event => {
  self.registration.unregister();
  event.waitUntil(
    caches
      .keys()
      .then(cacheNames =>
        cacheNames.filter(cacheName => cacheName.indexOf(DIRTY_CACHE) !== -1),
      )
      .then(cachesToDelete =>
        Promise.all(
          cachesToDelete.map(cacheToDelete => caches.delete(cacheToDelete)),
        ),
      )
      .then(() => self.clients.claim()),
  );
});

A more detailed explanation can be found in this article

Maybe is not the best strategy, but resolves the issue, probably due to a bad expires header.

zarpilla
  • 353
  • 3
  • 6