Search code examples
javascriptinstallationservice-workerpostmessage

How to report install progress back to the DOM?


Inside a service worker, inside the "install" handler, what is the proper way to report the DOM how many files have been cached and how many are still downloading ?

This question is only relevant when there are multiple MB of files to cache or when the connection is slow.


Solution

  • There are two ways to directly pass messages from your service worker to your client pages: using postMessage() and using the Broadcast Channel API.

    The Broadcast Channel API is a bit easier to use for this purpose, but it's not currently supported in Safari or Edge.

    In either case, it's up to you to decide how to format your message, and include the relevant state information from the service worker that the clients would need in order to display a message to the user.

    Here's a rough example of how the postMessage() approach might work:

    // In your service worker:
    self.addEventListener('install', async event => {
      event.waitUntil((async () => {
        const allUrls = [
          '/url1',
          '/url2',
          // etc.
        ];
    
        const alreadyCached = [];
    
        const clients = await self.clients.matchAll({
          includeUncontrolled: true,
        });
    
        const cache = await caches.open('my-cache-name');
        for (const url of allUrls) {
          await cache.add(url);
          alreadyCached.push(url);
          for (const client of clients) {
            client.postMessage({
              // Put whatever info you want here.
              alreadyCached,
              allUrls,
            });
          }
        }
      })());
    });
    
    // In your client pages:
    if ('serviceWorker' in navigator) {
      navigator.serviceWorker.addEventListener('message', event => {
        // event.data will contain {alreadyCached, allUrls}.
      });
    }