Missed the action at the 2018 Chrome Dev Summit? Catch up with our playlist on the Google Chrome Developers channel on YouTube. Watch now.

Common Recipes

This page contains a set of example caching strategies you can use with Workbox.

Google Fonts

The Google Fonts service consist of two parts:

  • The stylesheet with the @font-face definitions, which link to the font files.
  • The static, revisioned font files.

The stylesheet can change frequently, so it's best to use a caching strategy like stale while revalidate that checks for updates with every request. The font files themselves, on the other hand, do not change and can leverage a cache first strategy.

Here we've limited the age of the cached font files to one year (matching the HTTP Cache-Control header) and the max entries to 30 (to ensure we don't use up too much storage on the user's device).

// Cache the Google Fonts stylesheets with a stale-while-revalidate strategy.
workbox.routing.registerRoute(
  /^https:\/\/fonts\.googleapis\.com/,
  workbox.strategies.staleWhileRevalidate({
    cacheName: 'google-fonts-stylesheets',
  })
);

// Cache the underlying font files with a cache-first strategy for 1 year.
workbox.routing.registerRoute(
  /^https:\/\/fonts\.gstatic\.com/,
  workbox.strategies.cacheFirst({
    cacheName: 'google-fonts-webfonts',
    plugins: [
      new workbox.cacheableResponse.Plugin({
        statuses: [0, 200],
      }),
      new workbox.expiration.Plugin({
        maxAgeSeconds: 60 * 60 * 24 * 365,
        maxEntries: 30,
      }),
    ],
  })
);

Caching Images

You might want to use a cache-first images, by matching against a list of known extensions.

workbox.routing.registerRoute(
  /\.(?:png|gif|jpg|jpeg|svg)$/,
  workbox.strategies.cacheFirst({
    cacheName: 'images',
    plugins: [
      new workbox.expiration.Plugin({
        maxEntries: 60,
        maxAgeSeconds: 30 * 24 * 60 * 60, // 30 Days
      }),
    ],
  })
);

Cache CSS and JavaScript Files

You might want to use a stale-while-revalidate strategy for CSS and JavaScript files that aren't precached.

workbox.routing.registerRoute(
  /\.(?:js|css)$/,
  workbox.strategies.staleWhileRevalidate({
    cacheName: 'static-resources',
  })
);

Caching Content from Multiple Origins

You can create regular expressions to cache similar requests from multiple origins in a single route. For example, you can cache assets from origins like googleapis.com and gstatic.com with a single route.

workbox.routing.registerRoute(
  /.*(?:googleapis|gstatic)\.com/,
  workbox.strategies.staleWhileRevalidate(),
);

An alternative to the above example is to cache the origins separately to store assets in cache for each origin.

workbox.routing.registerRoute(
  /.*(?:googleapis)\.com/,
  workbox.strategies.staleWhileRevalidate({
    cacheName: 'googleapis',
  })
);

workbox.routing.registerRoute(
  /.*(?:gstatic)\.com/,
  workbox.strategies.staleWhileRevalidate({
    cacheName: 'gstatic',
  })
);

Restrict Caches for a Specific Origin

You can cache assets for a specific origin and apply expiration rules on that cache. For example, the example below caches up to 50 requests for up to 5 minutes.

workbox.routing.registerRoute(
  'https://hacker-news.firebaseio.com/v0/api',
  workbox.strategies.cacheFirst({
      cacheName: 'stories',
      plugins: [
        new workbox.expiration.Plugin({
          maxEntries: 50,
          maxAgeSeconds: 5 * 60, // 5 minutes
        }),
        new workbox.cacheableResponse.Plugin({
          statuses: [0, 200],
        }),
      ],
  })
);

Force a Timeout on Network Requests

There may be network requests that would be beneficial if they were served from the network, but could benefit by being served by the cache if the network request is taking too long.

For this, you can use a NetworkFirst strategy with the networkTimeoutSeconds option configured.

workbox.routing.registerRoute(
  'https://hacker-news.firebaseio.com/v0/api',
  workbox.strategies.networkFirst({
      networkTimeoutSeconds: 3,
      cacheName: 'stories',
      plugins: [
        new workbox.expiration.Plugin({
          maxEntries: 50,
          maxAgeSeconds: 5 * 60, // 5 minutes
        }),
      ],
  })
);

Cache Resources from a Specific Subdirectory

You can use a regular expression to easily route requests to files in a specific directory. If we wanted to route requests to files in /static/, we could use the regular expression new RegExp('/static/'), like so:

workbox.routing.registerRoute(
  new RegExp('/static/'),
  workbox.strategies.staleWhileRevalidate()
);

Cache Resources Based on Resource Type

You can use the RequestDestination enumerate type of the destination of the request to determine a strategy. For example, when the target is <audio> data:

workbox.routing.registerRoute(
  // Custom `matchCallback` function
  (context) => {
    if (context.event.request.destination === 'audio') {
      return true;
    }
    return null;
  },
  workbox.strategies.cacheFirst({
    cacheName: 'audio',
    plugins: [
      new workbox.expiration.Plugin({
        maxEntries: 60,
        maxAgeSeconds: 30 * 24 * 60 * 60, // 30 Days
      }),
    ],
  })
);

Access Caches from Your Web App's Code

The Cache Storage API is available for use in both service worker and in the context of window clients. If you want to make changes to caches—add or remove entries, or get a list of cached URLs—from the context of your web app, you can do so directly, without having to communicate with the service worker via postMessage().

For instance, if you wanted to add a URL to the a given cache in response to a user action in your web app, you can use code like the following:

// Inside app.js:

async function addToCache(urls) {
  const myCache = await window.caches.open('my-cache');
  await myCache.addAll(urls);
}

// Call addToCache whenever you'd like. E.g. to add to cache after a page load:
window.addEventListener('load', () => {
  // ...determine the list of related URLs for the current page...
  addToCache(['/static/relatedUrl1', '/static/relatedUrl2']);
});

The cache name, 'my-cache', can then be referred to when setting up a route in your service worker, and that route can take advantage of any cache entries that were added by the web page itself:

// Inside service-worker.js:

workbox.routing.registerRoute(
  new RegExp('/static/'),
  workbox.strategies.staleWhileRevalidate({
    cacheName: 'my-cache', // Use the same cache name as before.
  })
);