[ionic 5] How to correctly deploy an update of an Angular PWA?

After executing

ionic build --prod
# or
ionic cordova build browser --prod

and after uploading the files located in www or cordova/platforms/browser/www

How to deploy, correctly, these files? It happens that after uploading them, the PWA does not update automatically, and the ServiceWorker checker does not catch it.

Should I update all files? Including:

  • index.html
  • ngsw.json
  • manifiest.json

What do I do with the old “ng hashed files”? Do I erase them? i.e.:

  • 98-es5.47b01e7ba6bbd8f8658e.js
  • common-es5.1719b2b4dbadb25c2d74.js
  • runtime-es5.d9ee687d05b6194a4b29.js
  • main-es5.6c81c313ff50eb0e9515.js

I am serving the files with an Apache + PHP, and the .htaccess configuration contains:

  • Redirection of requests to index.html
<IfModule mod_rewrite.c>
  RewriteEngine On

  # Redirection to HTTPS:
  RewriteCond %{HTTPS} !on
  RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
  
  # Redirection of requests to index.html
  RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
  RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
  RewriteRule ^.*$ - [NC,L]
  RewriteRule (.*) index.html [NC,L]
</IfModule>
  • Disable browser caching for all files that don’t get a hash string by Angular ← Is this necessary and useful? (I currently put this part out as a comment)
<FilesMatch "^(?!.*\.([0-9a-z]{20})\.).*$">
  <IfModule mod_headers.c>
    FileETag None
    Header unset ETag
    Header unset Pragma
    Header unset Cache-Control
    Header unset Last-Modified
    Header set Pragma "no-cache"
    Header set Cache-Control "max-age=0, no-cache, no-store, must-revalidate"
    Header set Expires "Mon, 10 Apr 1972 00:00:00 GMT"
  </IfModule>
</FilesMatch>

Also, in the src/app.component.ts I have the service worker check:

async ngOnInit() {
    this.swUpdate.available.subscribe(async res => {
      const toast = await this.toastCtrl.create({
        message: 'Update available!',
        position: 'bottom',
        buttons: [{ role: 'cancel', text: 'Reload' }]
      });
      await toast.present();
      toast
        .onDidDismiss()
        .then(() => this.swUpdate.activateUpdate())
        .then(() => window.location.reload());
    });
    this.swUpdate.checkForUpdate();
    setInterval(() => {
      this.swUpdate.checkForUpdate();
    } , 15 * 60 * 1000);
  }

What’s wrong? Why isn’t my PWA updating immediately or never update?

1 Like

what is in your ngsw-config.json for installMode and updateMode ?

Can you put a console.log like f.e.

import { SwUpdate } from '@angular/service-worker/';

...

private swUpdate: SwUpdate

...

    if (!this.swUpdate.isEnabled) {
      console.log('swUpdate Enabled ? Nope :(');
    } else {
      console.log('swUpdate Enabled ? Yes :)');
      this.checkForUpdates();
    }
console.log('swUpdate.isEnabled: ' + this.swUpdate.isEnabled);

swUpdate.isEnabled: true

And my old ngsw-config.json was:

{
  "index": "/index.html",
  "assetGroups": [
    {
      "name": "app",
      "installMode": "prefetch",
      // "updateMode": "prefetch", ← now I'm trying with this
      "resources": {
        "files": [
          "/favicon.ico",
          "/index.html",
          "/*.css",
          "/*.js"
        ]
      }
    }, {
      "name": "assets",
      "installMode": "lazy",
      "updateMode": "prefetch",
      "resources": {
        "files": [
          "/assets/**",
          "/*.(eot|svg|cur|jpg|png|webp|gif|otf|ttf|woff|woff2|ani)"
        ]
      }
    }
  ]
}

Thank you for helping!

also check with “npm outdated” if your packages are still up-to-date

1 Like

:sweat_smile: It really had some outdated “beta” libraries and minor versions.

Testing again with the updates.

Thanks!

I hope it works out for you.

I always provide a button on a settings page so it is possible to force an update if needed.

yes, cool…
Thanks!