In an Angular (8) app I'd like to add a custom offline page (just a plain simple html-file to begin with).
I have set up my app as a PWA (using @angular/pwa
and configured everything so that it at least works smoothly while being online).
However, I've had a hard time making updates available for PWA users. So, after many hours of try and error I decided to exclude index.html
from the ngsw-config.json
. This has -of course- the effect that index.html
gets loaded every single time (not so bad, 'cause it's so small). If there are any updates index.html
links to different JS-files and these files get loaded immediately. So, as I said before, the PWA works just as I like it to be.
Now I want to display an offline.html
when the user starts the PWA being offline. So I've add offline.html
to ngsw-config.json
and I've created a custom Service Worker including the official ngsw-worker.js
:
importScripts('./ngsw-worker.js');
I'm also using this custom service worker instead of the official one:
ServiceWorkerModule.register('./custom-worker.js', { enabled: true, registrationStrategy: registrationStrategy })
So far, everything still works as expected. Behavior is just like before. Now I wanted to include the offline behavior in my custom worker:
importScripts('./ngsw-worker.js');
self.addEventListener('fetch', function(event) {
return event.respondWith(
caches.match(event.request)
.then(function(response) {
let requestToCache = event.request.clone();
return fetch(requestToCache).then().catch(error => {
// Check if the user is offline first and is trying to navigate to a web page
if (event.request.method === 'GET' && event.request.headers.get('accept').includes('text/html')) {
// Return the offline page
return caches.match("offline.html");
}
});
})
);
});
This script comes from: https://stackoverflow.com/a/56738140/4653997
Unfortunately this is the part that doesn't work at all. For now I'm pretty much stuck. I have no idea what do next.
I thought service workers get executed whether index.html
can get loaded or not.
Any help would be appreciated.
I've got it working!
In the end it was a relatively simple fetch
event listener I had to add to my custom service worker:
// listen to every fetch event
self.addEventListener('fetch', function (event) {
const request = event.request;
// filter for html document fetches (should only result in one single fetch) --> index.html
if (request.method === "GET" && request.destination === "document") {
// only intercept if there was a problem fetching index.html
event.respondWith(
fetch(request).catch(function (error) {
console.error("[onfetch] Failed. Serving cached offline fallback", error);
// return offline page from cache instead
return caches.match("/assets/offline.html");
}));
}
});
// use all the magic of the Angular Service Worker
importScripts('./ngsw-worker.js');