0

In order to handle cache in PWA, I am changing the name of the file ngsw-worker.js to ngsw-worker22.js (adding incremental number each time a new build is created) in main.ts

After the build I rename the generated ngsw-worker.js to ngsw-worker22.js as well.

When I run my app on browser, I get this error -

main-es2015.642820dbdb6b7b3ca0e0.js:1 Service worker registration failed with: DOMException: Failed to register a ServiceWorker for scope ('https://example.com/apptest/') with script ('https://example.com/apptest/ngsw-worker.js'): The script has an unsupported MIME type ('text/html').

Why is it still looking for ngsw-worker.js , when I see in console, it shows me registered?

Please note - My web app uses Cordova so the cached pages are of Cordova, as you can see in network, service workers are also working

enter image description here

enter image description here

halfer
  • 19,824
  • 17
  • 99
  • 186
user2828442
  • 2,415
  • 7
  • 57
  • 105

2 Answers2

1

You should not bind the SW name with a version and keep renaming it, since it can cause issues on the client.

What it can happen is that the browser will register the new SW (ngsw-worker22.js), but the old service worker remains installed too.

It is considered an anti-pattern (aka, bad practice) renaming a SW. You can simply change any of the files within the SW scope in order to alter its hashtable and tell the SW that new data is available on the server so the SW can cache it.

If you want to ship some metadata (like release notes) with each version, you can use the appData property in the ngsw.json file.

From Angular.io:

This section enables you to pass any data you want that describes this particular version of the app. The SwUpdate service includes that data in the update notifications. Many apps use this section to provide additional information for the display of UI popups, notifying users of the available update.

Like:

{
  "$schema": "./node_modules/@angular/service-worker/config/schema.json",
  "index": "/index.html",
  "appData": {
    "version": "1.0.0",
    "changelog": "Updated Angular to v.10.0.2"
  },
  "assetGroups": [
    {
     ...
    }
   ]
}

After a PROD build, your dist folder will have a ngsw.json file. Inside the target assets are registered in a hashtable like the example below. This hash values are used by the SW to determine if there is a new version of the asset on the Server as this ngsw.json file is downloaded at each page (re)load.

"hashTable": {        
    "/assets/icons/icon-152x152.png": "7479a9477815dfd9668d60f8b3b2fba709b91310",
    "/assets/icons/icon-512x512.png": "559d9c4318b45a1f2b10596bbb4c960fe521dbcc",
    "/assets/icons/icon-72x72.png": "c457e56089a36952cd67156f9996bc4ce54a5ed9",
    "/assets/icons/icon-96x96.png": "3914125a4b445bf111c5627875fc190f560daa41",
    "/favicon.ico": "84161b857f5c547e3699ddfbffc6d8d737542e01",
    "/index.html": "a975fbc21acc838a26b5a9f4a32f51cabefd66e6",
    "/main.3ad4b6e924d02c367683.js": "b4e507433cb30a760dfdc8b7591f25af2ddd0f1a",
    "/manifest.webmanifest": "88d5a912c54f29fe0743a02be3c6f208cc7d5880",
    "/styles.59cf8d767805b2930ef2.css": "93d8472f3f9e95fe245335903d6a64333fdbd353"
  },

BONUS INFO:
If you deploy a new version without a ngsw.json, as soon as the SW will detect that this file is missing (throwing a 404 Error) the SW Cache and the SW itself will be deleted. This is a sort of safety measure to remove potential malformed caches/SW versions and ensure that these are erased from the clients accessing the web app.

Francesco
  • 9,947
  • 7
  • 67
  • 110
  • If i dont do this, then even after multiple reloads it was not showing update, can you help me to understand why that was happening ? and how can i make sure it updates everytime. – user2828442 Jul 07 '20 at 05:56
  • The old SW version gets replaced after all browser tabs/windows where it is running are closed. Until then the new SW version gets installed but not activated. While developing you can tick the "update on reload" checkbox in the DevTools to see if that helps. Angular uses a hashmap in the ngsw.json file to register assets versions and the SW uses it to detect if new assets are available. You can also check that the new version you are deploying has new hasmaps there. If not, the new version is identical for the already installed SW. – Francesco Jul 07 '20 at 13:17
  • After build HashTable values are always same and when i check in browser , it says ngsw-worker.js received at 10:20 when i again upload build at 10:50, it is again showing same time but i see my new changes – user2828442 Jul 09 '20 at 06:09
  • i find - only index.html hash value changed – user2828442 Jul 09 '20 at 06:20
  • If index.html is in the hasTable and the hash is different, this should be enough to fetch the new data and show it at the next access (considering all Browser tabs/windows will be closed before then). If still not the case you should proof that the SW you get doesn't come from the browser cache. Here a good answer from Jeff about it -> https://stackoverflow.com/questions/38843970/service-worker-javascript-update-frequency-every-24-hours/38854905#38854905 – Francesco Jul 09 '20 at 07:25
0

I haven't used Cordova so perhaps there is some difference, but when I use Service Worker with Angular, the reference is in angular.json. This could be why your change is not taking effect.

"ngswConfigPath": "ngsw-config.json"

Having said that, I wonder why you are changing the service worker file name at all? The browser automatically detects a new version when the app is opened or refreshed. You don't have to do anything.

DevReboot
  • 161
  • 1
  • 7
  • it is not detecting the new version, i checked on multiple devices. Even after refreshing 3 to 4 times it was not taking effect. I use Ionic, i see the ngsw file in main.ts – user2828442 Jul 06 '20 at 07:07