A number of common patterns, especially around [routing](https://developer.chrome.com/docs/workbox/modules/workbox-routing.md.txt) and [caching](https://developer.chrome.com/docs/workbox/modules/workbox-strategies.md.txt), 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.md.txt) 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.md.txt) 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.md.txt) 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.md.txt#set_a_default_handler) method to create a route that applies the [`NetworkOnly`](https://developer.chrome.com/docs/workbox/modules/workbox-strategies.md.txt#network_only) strategy to all requests, as shown below. Other recipes, like the [page cache](https://developer.chrome.com/docs/workbox/modules/workbox-recipes.md.txt#page_cache), [static resource cache](https://developer.chrome.com/docs/workbox/modules/workbox-recipes.md.txt#static_resources_cache), or [image cache](https://developer.chrome.com/docs/workbox/modules/workbox-recipes.md.txt#image_cache), set up routes for their respective caches. `setDefaultHandler()` is not required when using both offline fallback and one of those recipes.

#### Recipe

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

setDefaultHandler(new NetworkOnly());

offlineFallback();
```

#### Pattern

```javascript
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.md.txt). This can be used as an alternative to [precaching](https://developer.chrome.com/docs/workbox/modules/workbox-precaching.md.txt) 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

```javascript
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

```javascript
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.md.txt#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.md.txt#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

```javascript
import {pageCache} from 'workbox-recipes';

pageCache();
```

#### Pattern

```javascript
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.md.txt#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.md.txt#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

```javascript
import {staticResourceCache} from 'workbox-recipes';

staticResourceCache();
```

#### Pattern

```javascript
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.md.txt#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.md.txt#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

```javascript
import {imageCache} from 'workbox-recipes';

imageCache();
```

#### Pattern

```javascript
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.md.txt#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.md.txt#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

```javascript
import {googleFontsCache} from 'workbox-recipes';

googleFontsCache();
```

#### Pattern

```javascript
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.md.txt#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.md.txt#stale-while-revalidate) strategy, respond to image requests with a [cache first](https://developer.chrome.com/docs/workbox/modules/workbox-strategies.md.txt#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:

```javascript
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.md.txt#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.md.txt#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.md.txt#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.md.txt#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.md.txt#type-StaticResourceOptions) optional

### warmStrategyCache()

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

#### Parameters

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

<br />