workbox-recipes

A number of common patterns, especially around routing and caching, are common enough that they can be standardized into reusable recipes. workbox-recipes makes these available in an easy-to-consume package, allowing you to get up-and-running with a highly functional service worker quickly.

Recipes

Each recipe combines a number of Workbox modules together, bundling them into commonly used patterns. The recipes below will show the recipe you use when using this module, and the equivalent pattern it's using under the hood, should you want to write it yourself.

Offline fallback

The offline fallback recipe allows your service worker to serve a web page, image, or font if there's a routing error for any of the three, for instance if a user is offline and there isn't a cache hit. In version 6.1.0 of Workbox Recipes, the requirement to cache these items using precaching was removed; for backwards compatibility, it will look for items in the precache first before trying its own cache.

This recipe, by default, assumes the fallback page is offline.html and that there isn't an image or font fallback. See the offline fallback options for a list of all configuration options.

The offline fallback will only be applied if there's a matching route for a given request. If you're using the offline fallback recipe on its own, you'll need to create routes yourself. The simplest way to do is to use the setDefaultHandler() method to create a route that applies the NetworkOnly strategy to all requests, as shown below. Other recipes, like the page cache, static resource cache, or image cache, set up routes for their respective caches. setDefaultHandler() is not required when using both offline fallback and one of those recipes.

Recipe

import {offlineFallback} from 'workbox-recipes';
import {setDefaultHandler} from 'workbox-routing';
import {NetworkOnly} from 'workbox-strategies';

setDefaultHandler(new NetworkOnly());

offlineFallback();

Pattern

import {setCatchHandler, setDefaultHandler} from 'workbox-routing';
import {NetworkOnly} from 'workbox-strategies';

const pageFallback = 'offline.html';
const imageFallback = false;
const fontFallback = false;

setDefaultHandler(new NetworkOnly());

self.addEventListener('install', event => {
  const files = [pageFallback];
  if (imageFallback) {
    files.push(imageFallback);
  }
  if (fontFallback) {
    files.push(fontFallback);
  }

  event.waitUntil(
    self.caches
      .open('workbox-offline-fallbacks')
      .then(cache => cache.addAll(files))
  );
});

const handler = async options => {
  const dest = options.request.destination;
  const cache = await self.caches.open('workbox-offline-fallbacks');

  if (dest === 'document') {
    return (await cache.match(pageFallback)) || Response.error();
  }

  if (dest === 'image' && imageFallback !== false) {
    return (await cache.match(imageFallback)) || Response.error();
  }

  if (dest === 'font' && fontFallback !== false) {
    return (await cache.match(fontFallback)) || Response.error();
  }

  return Response.error();
};

setCatchHandler(handler);

Warm strategy cache

The warm strategy cache recipe allows you to load provided URLs into your cache during the service worker's install phase, caching them with the options of the provided strategy. This can be used as an alternative to precaching if you know the specific URLs you'd like to cache, want to warm the cache of a route, or similar places where you'd like cache URLs during installation.

See the warm strategy cache options for a list of all configuration options.

Recipe

import {warmStrategyCache} from 'workbox-recipes';
import {CacheFirst} from 'workbox-strategies';

// This can be any strategy, CacheFirst used as an example.
const strategy = new CacheFirst();
const urls = ['/offline.html'];

warmStrategyCache({urls, strategy});

Pattern

import {CacheFirst} from 'workbox-strategies';
// This can be any strategy, CacheFirst used as an example.
const strategy = new CacheFirst();
const urls = ['/offline.html'];

self.addEventListener('install', event => {
  // handleAll returns two promises, the second resolves after all items have been added to cache.
  const done = urls.map(
    path =>
      strategy.handleAll({
        event,
        request: new Request(path),
      })[1]
  );

  event.waitUntil(Promise.all(done));
});

Page cache

The page cache recipe allows your service worker to respond to a request for an HTML page (through URL navigation) with a network first caching strategy, optimized to, ideally, allow for the cache fallback to arrive quick enough for for a largest contentful paint score of less than 4.0 seconds.

This recipe, by default, assumes the network timeout should be 3 seconds and supports cache warming through the warmCache option. See the page cache options for a list of all configuration options.

Recipe

import {pageCache} from 'workbox-recipes';

pageCache();

Pattern

import {registerRoute} from 'workbox-routing';
import {NetworkFirst} from 'workbox-strategies';
import {CacheableResponsePlugin} from 'workbox-cacheable-response';

const cacheName = 'pages';
const matchCallback = ({request}) => request.mode === 'navigate';
const networkTimeoutSeconds = 3;

registerRoute(
  matchCallback,
  new NetworkFirst({
    networkTimeoutSeconds,
    cacheName,
    plugins: [
      new CacheableResponsePlugin({
        statuses: [0, 200],
      }),
    ],
  })
);

Static resources cache

The static resources cache recipe allows your service worker to respond to a request for static resources, specifically CSS, JavaScript, and Web Worker requests, with a stale-while-revalidate caching strategy so those assets can be quickly served from the cache and be updated in the background

This recipe supports cache warming through the warmCache option. See the static resources cache options for a list of all configuration options.

Recipe

import {staticResourceCache} from 'workbox-recipes';

staticResourceCache();

Pattern

import {registerRoute} from 'workbox-routing';
import {StaleWhileRevalidate} from 'workbox-strategies';
import {CacheableResponsePlugin} from 'workbox-cacheable-response';

const cacheName = 'static-resources';
const matchCallback = ({request}) =>
  // CSS
  request.destination === 'style' ||
  // JavaScript
  request.destination === 'script' ||
  // Web Workers
  request.destination === 'worker';

registerRoute(
  matchCallback,
  new StaleWhileRevalidate({
    cacheName,
    plugins: [
      new CacheableResponsePlugin({
        statuses: [0, 200],
      }),
    ],
  })
);

Image cache

The image cache recipe allows your service worker to respond to a request for images with a cache-first caching strategy so that once they're available in cache a user doesn't need to make another request for them.

This recipe, by default, caches a maximum of 60 images, each for 30 days and supports cache warming through the warmCache option. See the image cache options for a list of all configuration options.

Recipe

import {imageCache} from 'workbox-recipes';

imageCache();

Pattern

import {registerRoute} from 'workbox-routing';
import {CacheFirst} from 'workbox-strategies';
import {CacheableResponsePlugin} from 'workbox-cacheable-response';
import {ExpirationPlugin} from 'workbox-expiration';

const cacheName = 'images';
const matchCallback = ({request}) => request.destination === 'image';
const maxAgeSeconds = 30 * 24 * 60 * 60;
const maxEntries = 60;

registerRoute(
  matchCallback,
  new CacheFirst({
    cacheName,
    plugins: [
      new CacheableResponsePlugin({
        statuses: [0, 200],
      }),
      new ExpirationPlugin({
        maxEntries,
        maxAgeSeconds,
      }),
    ],
  })
);

Google Fonts cache

The Google Fonts recipe caches the two parts of a Google Fonts request:

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

Because the stylesheet can change frequently, a stale-while-revalidate caching strategy is used. The font files themselves, on the other hand, do not change and can leverage a cache first strategy.

This recipe, by default, caches a maximum of 30 font files, each for one year. See the Google Fonts cache options for a list of all configuration options.

Recipe

import {googleFontsCache} from 'workbox-recipes';

googleFontsCache();

Pattern

import {registerRoute} from 'workbox-routing';
import {StaleWhileRevalidate} from 'workbox-strategies';
import {CacheFirst} from 'workbox-strategies';
import {CacheableResponsePlugin} from 'workbox-cacheable-response';
import {ExpirationPlugin} from 'workbox-expiration';

const sheetCacheName = 'google-fonts-stylesheets';
const fontCacheName = 'google-fonts-webfonts';
const maxAgeSeconds = 60 * 60 * 24 * 365;
const maxEntries = 30;

registerRoute(
  ({url}) => url.origin === 'https://fonts.googleapis.com',
  new StaleWhileRevalidate({
    cacheName: sheetCacheName,
  })
);

// Cache the underlying font files with a cache-first strategy for 1 year.
registerRoute(
  ({url}) => url.origin === 'https://fonts.gstatic.com',
  new CacheFirst({
    cacheName: fontCacheName,
    plugins: [
      new CacheableResponsePlugin({
        statuses: [0, 200],
      }),
      new ExpirationPlugin({
        maxAgeSeconds,
        maxEntries,
      }),
    ],
  })
);

Quick usage

Combining all of the recipes together will yield a service worker that responds to page requests with a network first caching strategy, respond to CSS, JavaScript, and Web Worker requests with a stale-while-revalidate strategy, respond to image requests with a cache first strategy, properly cache Google Fonts, and provide an offline fallback for page requests. This can all be done with the following:

import {
  pageCache,
  imageCache,
  staticResourceCache,
  googleFontsCache,
  offlineFallback,
} from 'workbox-recipes';

pageCache();

googleFontsCache();

staticResourceCache();

imageCache();

offlineFallback();

Types

GoogleFontCacheOptions

Properties

  • cachePrefix

    string optional

  • maxAgeSeconds

    number optional

  • maxEntries

    number optional

ImageCacheOptions

Properties

  • cacheName

    string optional

  • matchCallback
  • maxAgeSeconds

    number optional

  • maxEntries

    number optional

  • plugins

    WorkboxPlugin[] optional

  • warmCache

    string[] optional

OfflineFallbackOptions

Properties

  • fontFallback

    string optional

  • imageFallback

    string optional

  • pageFallback

    string optional

PageCacheOptions

Properties

  • cacheName

    string optional

  • matchCallback
  • networkTimeoutSeconds

    number optional

  • plugins

    WorkboxPlugin[] optional

  • warmCache

    string[] optional

StaticResourceOptions

Properties

WarmStrategyCacheOptions

Properties

Methods

googleFontsCache()

workbox-recipes.googleFontsCache(
  options?: GoogleFontCacheOptions,
)

An implementation of the [Google fonts]https://developers.google.com/web/tools/workbox/guides/common-recipes#google_fonts caching recipe

Parameters

imageCache()

workbox-recipes.imageCache(
  options?: ImageCacheOptions,
)

An implementation of the [image caching recipe]https://developers.google.com/web/tools/workbox/guides/common-recipes#caching_images

Parameters

offlineFallback()

workbox-recipes.offlineFallback(
  options?: OfflineFallbackOptions,
)

An implementation of the [comprehensive fallbacks recipe]https://developers.google.com/web/tools/workbox/guides/advanced-recipes#comprehensive_fallbacks. Be sure to include the fallbacks in your precache injection

Parameters

pageCache()

workbox-recipes.pageCache(
  options?: PageCacheOptions,
)

An implementation of a page caching recipe with a network timeout

Parameters

staticResourceCache()

workbox-recipes.staticResourceCache(
  options?: StaticResourceOptions,
)

An implementation of the [CSS and JavaScript files recipe]https://developers.google.com/web/tools/workbox/guides/common-recipes#cache_css_and_javascript_files

Parameters

warmStrategyCache()

workbox-recipes.warmStrategyCache(
  options: WarmStrategyCacheOptions,
)

Parameters