A number of common patterns, especially around [routing](https://developer.chrome.com/docs/workbox/modules/workbox-routing) and [caching](https://developer.chrome.com/docs/workbox/modules/workbox-strategies), 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](https://developer.chrome.com/docs/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](https://developer.chrome.com/docs/workbox/modules/workbox-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](https://developer.chrome.com/docs/workbox/reference/workbox-recipes#method-offlineFallback) for a list of all configuration options.

The offline fallback will only be applied if there's a matching [route](https://developer.chrome.com/docs/workbox/modules/workbox-routing) 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()`](https://developer.chrome.com/docs/workbox/modules/workbox-routing#set_a_default_handler) method to create a route that applies the [`NetworkOnly`](https://developer.chrome.com/docs/workbox/modules/workbox-strategies#network_only) strategy to all requests, as shown below. Other recipes, like the [page cache](https://developer.chrome.com/docs/workbox/modules/workbox-recipes#page_cache), [static resource cache](https://developer.chrome.com/docs/workbox/modules/workbox-recipes#static_resources_cache), or [image cache](https://developer.chrome.com/docs/workbox/modules/workbox-recipes#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](https://developer.chrome.com/docs/workbox/modules/workbox-strategies). This can be used as an alternative to [precaching](https://developer.chrome.com/docs/workbox/modules/workbox-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](https://developer.chrome.com/docs/workbox/reference/workbox-recipes#method-warmStrategyCache) 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](https://developer.chrome.com/docs/workbox/modules/workbox-strategies#network_first_network_falling_back_to_cache) caching strategy, optimized to, ideally, allow for the cache fallback to arrive quick enough for for a [largest contentful paint](https://web.dev/articles/vitals) score of less than 4.0 seconds.

This recipe, by default, assumes the network timeout should be 3 seconds and supports [cache warming](https://developer.chrome.com/docs/workbox/modules/workbox-recipes#warm_strategy_cache) through the `warmCache` option. See the [page cache options](https://developer.chrome.com/docs/workbox/reference/workbox-recipes#method-pageCache) 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](https://developer.chrome.com/docs/workbox/modules/workbox-strategies#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](https://developer.chrome.com/docs/workbox/modules/workbox-recipes#warm_strategy_cache) through the `warmCache` option. See the [static resources cache options](https://developer.chrome.com/docs/workbox/reference/workbox-recipes#method-staticResourceCache) 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](https://developer.chrome.com/docs/workbox/modules/workbox-strategies#cache_first_cache_falling_back_to_network) 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](https://developer.chrome.com/docs/workbox/modules/workbox-recipes#warm_strategy_cache) through the `warmCache` option. See the [image cache options](https://developer.chrome.com/docs/workbox/reference/workbox-recipes#method-imageCache) 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](https://developer.chrome.com/docs/workbox/modules/workbox-strategies#stale-while-revalidate) caching strategy is used. The font files themselves, on the other hand, do not change and can leverage a [cache first](https://developer.chrome.com/docs/workbox/modules/workbox-strategies#cache_first_cache_falling_back_to_network) strategy.

This recipe, by default, caches a maximum of 30 font files, each for one year. See the [Google Fonts cache options](https://developer.chrome.com/docs/workbox/reference/workbox-recipes#method-googleFontsCache) 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](https://developer.chrome.com/docs/workbox/modules/workbox-strategies#network_first_network_falling_back_to_cache) caching strategy, respond to CSS, JavaScript, and Web Worker requests with a [stale-while-revalidate](https://developer.chrome.com/docs/workbox/modules/workbox-strategies#stale-while-revalidate) strategy, respond to image requests with a [cache first](https://developer.chrome.com/docs/workbox/modules/workbox-strategies#cache_first_cache_falling_back_to_network) 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();

<br />

## Types

### GoogleFontCacheOptions

#### Properties

- cachePrefix string optional
- maxAgeSeconds number optional
- maxEntries number optional

### ImageCacheOptions

#### Properties

- cacheName string optional
- matchCallback [RouteMatchCallback](https://developer.chrome.com/docs/workbox/workbox-core/#method-RouteMatchCallback) optional
- maxAgeSeconds number optional
- maxEntries number optional
- plugins [WorkboxPlugin](https://developer.chrome.com/docs/workbox/workbox-core/#type-WorkboxPlugin)\[\] optional
- warmCache string\[\] optional

### OfflineFallbackOptions

#### Properties

- fontFallback string optional
- imageFallback string optional
- pageFallback string optional

### PageCacheOptions

#### Properties

- cacheName string optional
- matchCallback [RouteMatchCallback](https://developer.chrome.com/docs/workbox/workbox-core/#method-RouteMatchCallback) optional
- networkTimeoutSeconds number optional
- plugins [WorkboxPlugin](https://developer.chrome.com/docs/workbox/workbox-core/#type-WorkboxPlugin)\[\] optional
- warmCache string\[\] optional

### StaticResourceOptions

#### Properties

- cacheName string optional
- matchCallback [RouteMatchCallback](https://developer.chrome.com/docs/workbox/workbox-core/#method-RouteMatchCallback) optional
- plugins [WorkboxPlugin](https://developer.chrome.com/docs/workbox/workbox-core/#type-WorkboxPlugin)\[\] optional
- warmCache string\[\] optional

### WarmStrategyCacheOptions

#### Properties

- strategy [Strategy](https://developer.chrome.com/docs/workbox/workbox-strategies/#type-Strategy)
- urls string\[\]

## Methods

### googleFontsCache()

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

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

#### Parameters

- options [GoogleFontCacheOptions](https://developer.chrome.com/docs/workbox/modules/workbox-recipes#type-GoogleFontCacheOptions) optional

### imageCache()

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

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

#### Parameters

- options [ImageCacheOptions](https://developer.chrome.com/docs/workbox/modules/workbox-recipes#type-ImageCacheOptions) optional

### offlineFallback()

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

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

- options [OfflineFallbackOptions](https://developer.chrome.com/docs/workbox/modules/workbox-recipes#type-OfflineFallbackOptions) optional

### pageCache()

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

An implementation of a page caching recipe with a network timeout

#### Parameters

- options [PageCacheOptions](https://developer.chrome.com/docs/workbox/modules/workbox-recipes#type-PageCacheOptions) optional

### staticResourceCache()

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

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

- options [StaticResourceOptions](https://developer.chrome.com/docs/workbox/modules/workbox-recipes#type-StaticResourceOptions) optional

### warmStrategyCache()

```typescript
workbox-recipes.warmStrategyCache(
  options: WarmStrategyCacheOptions,
): void
```

#### Parameters

- options [WarmStrategyCacheOptions](https://developer.chrome.com/docs/workbox/modules/workbox-recipes#type-WarmStrategyCacheOptions)

<br />