0

I am trying to do some performance improvements for our web app by using web workers. I need to include some scripts that I was using importScripts(). But the conundrum is that importScripts fails when trying to access offline. How do I access these files offline using Cache API? Do I need to implement custom reader for reading ReadableStream? Is there a better standard to implement offline cache access inside web workers?

Details

These files are javascript scripts which have some custom js and external libraries like CryptoJS and LocalForage. I would like to implement - Network falling back to Cache paradigm using CacheAPI/Service Workers.

I initially implemented a standard Service Worker with an install and fetch event listeners but I believe the scope between the service worker and the web worker was not the same. After some research on MDN and exploration, I see that Cache API is available within the WebWorkerScope so I moved the cache call within the web worker scope.

I have tried various ways of accessing these files by using fetch events and just getting the files from cache. I get a response back after my promises resolve but the body of the response is a readable stream and I am not sure how to resolve that.

Any help or pointers would be really appreciated.

My web worker invocation

var worker = new Worker('Path');

I have attempted to follow the write up as a guide - https://developers.google.com/web/ilt/pwa/caching-files-with-service-worker

// Web Worker
self.addEventListener('fetch', function(event){
    event.respondWith(
        fetch(event.request).catch(function(){
            return caches.match(event.request);
        })
    )
});

caches.open('mcaseworker').then(function(cache){
    var urlList = ['/resources/scripts/custom/globalConfig.js',
                    '/resources/scripts/localforage/localforage.min.js'
                    '/resources/scripts/utility/pako.js',
                    '/resources/scripts/cryptojs/aes.js',
                    '/resources/scripts/cryptojs/sha1.js'
                ];
    // Initialize a promise all with the list of urls
    Promise.all(urlList.map(function(url){
        return fetch(url, {
            headers : {
                'Content-Type' : 'application/x-javascript'
            }
        })
        .then(function(response){
            if (response){
                return response;
            }
        });
    }))
    .then(function(values){
        Promise.all(values.map(function(value){
            return value;
        }))
        .then(function(res){
            // Custom Code
            // Would like to access localforage and other javascript libraries. 
        })
    })
})

Response after promises resolve. enter image description here

1 Answers1

1

Web workers don't have a fetch event, so your code listening on the fetch event will never trigger. You should put your cache and fetch event listener in a service worker.

Main code:

if ('serviceWorker' in navigator) {
  // Register a service worker hosted at the root of the
  // site using the default scope.
  navigator.serviceWorker.register('/sw.js').then(function(registration) {
    console.log('Service worker registration succeeded:', registration);
  }, /*catch*/ function(error) {
    console.log('Service worker registration failed:', error);
  });
} else {
  console.log('Service workers are not supported.');
}


const worker = new Worker("/worker.js");

sw.js

self.addEventListener('fetch', function(event){
    event.respondWith(
        fetch(event.request).catch(function(){
            return caches.match(event.request);
        })
    )
});

//Add cache opening code here

worker.js

// Import scripts here
importScripts('/resources/scripts/localforage/localforage.min.js');

You can see this answer for more information about the difference between web workers and service workers.

jro
  • 900
  • 1
  • 10
  • 21
  • 1
    This is exactly what I did yesterday and got it to work. Thank you for the confirmation. Marking it as the answer for anyone who stumbles upon the post. – dablackreaper Mar 27 '19 at 17:27
  • 1
    Marking jro's answer as correct. Service Worker and Web Workers will work in conjunction. Web Workers would fetch and Service worker would service the request. An oversight on my part was the scoping as well. Service Worker and Web Workers need to be at the root of all the resources you want to fetch/cache using them. – dablackreaper Mar 27 '19 at 17:43