quackr
quackr

Reputation: 21

Firebase Hosting (Angular 8 + Service Worker) not updating on a refresh

I own quackr.io and have run into some trouble with users not seeing the new version of my code. quackr is a PWA (Angular SSR + Service worker) deployed onto Firebase hosting.

Whenever I deploy a new version, anyone who has viewed the site previously will see the old version. If you do a hard refresh you will see the new version. However if you do another normal page refresh it will revert back to the old version.

Here's my firebase.json (i was hoping adding no-cache to the service worker js it would invalidate upon deploying but it didn't work):

{
  "hosting": {
    "public": "dist/browser",
    "headers": [
    {
      "source": "/@(ngsw-worker.js|ngsw.json)",
      "headers": [
        {
          "key": "Cache-Control",
          "value": "no-cache"
        }
      ]
  } 
  ],
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    "rewrites": [
      {
        "source": "**",
        "function": "ssr"
      }
    ]
  },
  "functions": {
    "predeploy": [
      "npm --prefix \"$RESOURCE_DIR\" run lint",
      "npm --prefix \"$RESOURCE_DIR\" run build"
    ]
  }
}

ngsw-config.json:

{
  "index": "/index.html",
  "appData": {
    "name": "quackr.io",
    "description": "v2.0"
  },
  "assetGroups": [{
    "name": "app",
    "installMode": "prefetch",
    "resources": {
      "files": [
        "/favicon.ico",
        "/index.html",
        "/*.css",
        "/*.js"
      ]
    }
  }, {
    "name": "assets",
    "installMode": "lazy",
    "updateMode": "prefetch",
    "resources": {
      "files": [
        "/assets/**"
      ]
    }
  },
  {
    "name": "fonts",
    "resources": {
      "urls": [
        "https://fonts.googleapis.com/**"
      ]
    }
  }]
}

https://quackr.io/ngsw-worker.js

Any help would be appreciated, thanks guys!

Upvotes: 1

Views: 1897

Answers (1)

Nadhir Falta
Nadhir Falta

Reputation: 5267

You will need to use Angular's service worker update functionality, which will watch for any new changes in the app, and then either refresh the page or notify the user about the updates and give them the option to refresh themselves:

see this example:

constructor(
        private swUpdate: SwUpdate,
        private snackbar: MatSnackBar
    ) {
        this.swUpdate.available.subscribe(evt => {
            const snack: any = this.snackbar.open(`Updates Available`, 'Reload');

            snack.onAction().subscribe(() => {
                window.location.reload();
            });

            snack.setTimeout(() => {
                snack.dismiss();
            }, 6000);
        });
    }

Original Docs:
https://angular.io/api/service-worker/SwUpdate

More info:
https://alligator.io/angular/service-worker-updates/

Here is my Firebase.json file

{
  "hosting": {
    "public": "dist/myApp",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    "headers": [
      {
        "source": "**/*.@(eot|otf|ttf|ttc|woff|woff2|font.css)",
        "headers": [
          {
            "key": "Access-Control-Allow-Origin",
            "value": "max-age=31557600"
          }
        ]
      },
      {
        "source": "**/*.@(js|css)",
        "headers": [
          {
            "key": "Cache-Control",
            "value": "max-age=31557600"
          }
        ]
      },
      {
        "source": "**/*.@(svg|ico|json|mp3)",
        "headers": [
          {
            "key": "Cache-Control",
            "value": "max-age=31557600"
          }
        ]
      }
    ],
    "rewrites": [
      {
        "source": "**",
        "function": "ssr"
      }
    ]
  },
  "functions": {
    "predeploy": [
      "npm --prefix %RESOURCE_DIR% run lint",
      "npm --prefix %RESOURCE_DIR% run build"
    ],
    "source": "functions"
  },
  "emulators": {
    "functions": {
      "port": "5005"
    }
  },
  "firestore": {
    "rules": "firestore.rules",
    "indexes": "firestore.indexes.json"
  }
}

Upvotes: 1

Related Questions