Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Service worker : fetch event listener is never triggered by HTTP GET requests to an API on Angular 7

I used @angular/service-worker module to generate a service-worker to cache all static assets for my Angular 7 app and it works well (in network tab on chrome dev tools, these files are tagged as from ServiceWorker).

What I am trying to do is adding cache support (and background sync) to data got from an external API. I know that @angular/service-worker module supports dataGroups type of assets but I would like to do something more complicated : serving cache data first then fetch data through network, update the cache and finally return a second, fresher response. This idea is described in the offline cookbook : https://developers.google.com/web/fundamentals/instant-and-offline/offline-cookbook/#cache-then-network So I need to add a custom SW coexisting with the one generated by Angular. Problem is my fetch event listener is never fired.

I register my service worker : ServiceWorkerModule.register('../sw.js', { enabled: environment.production }), in app.module.ts.

sw.js file imports ngsw-worker.js (which is generated by Angular) :

importScripts('./ngsw-worker.js');
importScripts('./sw-custom.js');

Then, sw-custom.js is adding two events listener on install and fetch :

self.addEventListener('install', function(event) {
    try {
        console.log('typeof System in install', typeof System);
    } catch(e){}

    console.log('caching');
    event.waitUntil(
        caches.open(CACHE_VERSION).then(function(cache) {
            console.log('caching - getting');
            return;
        }).catch(function(error){ console.log('error', error) })
    );
  });

  self.addEventListener('fetch', event => {
    console.log('Hello service worker');
    if (event.request.method !== 'GET') return;
    const request = event.request.clone();
    // Do stuff
    event.respondWith(fetch(request));
  });

The listener on install event is executed, but not the fetch one and I can't understand why.

like image 235
maxsoulard Avatar asked Nov 16 '22 15:11

maxsoulard


1 Answers

The problem is that you're importing Angular ngsw-worker.js first, it contains it's own listeners that can prevent your listener from being executed.

Try changing the import order like this:

importScripts('./sw-custom.js');
importScripts('./ngsw-worker.js');

Also, you may need to prevent angular generated listeners to run by stopping the event propagation avoiding things like duplicate fetches:

  self.addEventListener('fetch', event => {
    console.log('Hello service worker');
    if (event.request.method !== 'GET') return;
    const request = event.request.clone();
    // Do stuff
    event.respondWith(fetch(request));

    // stop propagation to Angular Service Worker if we need
    event.stopImmediatePropagation();
  });
like image 71
gcampos Avatar answered Nov 24 '22 00:11

gcampos