robinnnnn
robinnnnn

Reputation: 1735

Using service workers to both use cache *and* update in background

I understand that ServiceWorkers can grab responses out of cached network requests.

That said, is it possible to have these workers continue to update the cache in the background?

Consider the following scenario: a user logs into an app where they have cached data, and is immediately greeted with "Welcome, <cached_username>!"

Is it be possible for the service worker to continue to make the network request after serving a cache match? The user could've updated their username to new_username on another device, and it would be great to get the UI eventually consistent.

I still want to make network requests, while also utilizing ServiceWorkers for that speedy initial render.

Upvotes: 1

Views: 1069

Answers (1)

Jeff Posnick
Jeff Posnick

Reputation: 56144

What you're describing is very similar to the stale-while-revalidate strategy.

The basic recipe in that cookbook doesn't include any code for having the service worker notify the client page(s) when the revalidation step finds an update, though.

If you were to use Workbox inside your service worker, you could accomplish that notification step using the workbox-broadcast-update module along with a few other modules:

In your service worker:

import {registerRoute} from 'workbox-routing';
import {StaleWhileRevalidate} from 'workbox-strategies';
import {BroadcastUpdatePlugin} from 'workbox-broadcast-update';

registerRoute(
  // Adjust this to match your cached data requests:
  new RegExp('/api/'),
  new StaleWhileRevalidate({
    plugins: [
      new BroadcastUpdatePlugin(),
    ],
  })
);

In your web app:


navigator.serviceWorker.addEventListener('message', async (event) => {
  // Optional: ensure the message came from workbox-broadcast-update
  if (event.data.meta === 'workbox-broadcast-update') {
    const {cacheName, updatedUrl} = event.data.payload;

    // Do something with cacheName and updatedUrl.
    // For example, get the cached content and update
    // the content on the page.
    const cache = await caches.open(cacheName);
    const updatedResponse = await cache.match(updatedUrl);
    const updatedText = await updatedResponse.text();
  }
});

Upvotes: 1

Related Questions