# Workbox

> What Workbox is, how its modular packages map to service worker tasks, and how to add it to a project with or without a build tool.

**In one line:** Workbox is Google's production-grade service worker library. It replaces hand-rolled `fetch` event logic with composable modules for routing, caching strategies, precaching, background sync, and expiration — while staying close to the raw Service Workers API.

## What Workbox provides

| Module | Purpose |
|---|---|
| `workbox-routing` | Route `fetch` events to different handlers by URL pattern or request property |
| `workbox-strategies` | `CacheFirst`, `NetworkFirst`, `StaleWhileRevalidate`, `NetworkOnly`, `CacheOnly` implementations |
| `workbox-precaching` | Manifest-driven precaching with integrity verification and cache cleanup |
| `workbox-expiration` | Bound cache size and TTL on any cache |
| `workbox-cacheable-response` | Filter cacheable responses by status code or header |
| `workbox-background-sync` | Queue failed POST requests and replay when connectivity returns |
| `workbox-broadcast-update` | Notify pages when a cached response is updated |
| `workbox-google-analytics` | Buffer offline analytics events and replay on reconnect |

## Installation

### CDN (no build tool)

```js
// sw.js
import { registerRoute } from 'https://cdn.jsdelivr.net/npm/workbox-routing@7/registerRoute.mjs';
import { CacheFirst } from 'https://cdn.jsdelivr.net/npm/workbox-strategies@7/CacheFirst.mjs';

registerRoute(
  ({ request }) => request.destination === 'image',
  new CacheFirst({ cacheName: 'images' })
);
```

### npm (with a bundler)

```sh
npm install workbox-routing workbox-strategies workbox-precaching
```

```js
// sw.js (bundled)
import { registerRoute } from 'workbox-routing';
import { CacheFirst, NetworkFirst } from 'workbox-strategies';
```

### `workbox-window` (in the page)

```sh
npm install workbox-window
```

```js
import { Workbox } from 'workbox-window';

const wb = new Workbox('/sw.js');
wb.register();

// Listen for an update and notify the user
wb.addEventListener('waiting', () => {
  if (confirm('New version available. Reload?')) {
    wb.messageSkipWaiting();
    window.location.reload();
  }
});
```

`workbox-window` handles registration, update detection, and `skipWaiting` messaging — the boilerplate that otherwise lives in every page.

## Precaching with `workbox-precaching`

Precaching uses a manifest (generated at build time) to cache a list of versioned URLs. Workbox tracks the manifest hash and only re-fetches entries whose content has changed:

```js
import { precacheAndRoute } from 'workbox-precaching';

// __WB_MANIFEST is injected by the Workbox build tool (injectManifest / generateSW)
precacheAndRoute(self.__WB_MANIFEST);
```

Build tools that produce this manifest: `workbox-webpack-plugin` (via `InjectManifest` or `GenerateSW`), `workbox-vite-plugin`, `workbox-cli`, and `@ducanh2912/next-pwa`.

## Routing

```js
import { registerRoute, NavigationRoute } from 'workbox-routing';
import { NetworkFirst, CacheFirst, StaleWhileRevalidate } from 'workbox-strategies';
import { CacheableResponsePlugin } from 'workbox-cacheable-response';
import { ExpirationPlugin } from 'workbox-expiration';

// Pages (SPA and MPA)
registerRoute(
  new NavigationRoute(new NetworkFirst({ cacheName: 'pages' }))
);

// Images with expiration
registerRoute(
  ({ request }) => request.destination === 'image',
  new CacheFirst({
    cacheName: 'images',
    plugins: [
      new CacheableResponsePlugin({ statuses: [200] }),
      new ExpirationPlugin({ maxEntries: 60, maxAgeSeconds: 30 * 24 * 60 * 60 }),
    ],
  })
);

// Fonts — stale-while-revalidate, long-lived
registerRoute(
  ({ request }) => request.destination === 'font',
  new StaleWhileRevalidate({ cacheName: 'fonts' })
);
```

## `GenerateSW` vs `InjectManifest`

| Mode | What Workbox does | When to use |
|---|---|---|
| `GenerateSW` | Generates a complete `sw.js` from your config | Simple apps; no custom logic needed in the worker |
| `InjectManifest` | Injects the precache manifest into your own `sw.js` template | You need custom routing, background sync, or any code beyond precaching |

## What Workbox does not cover

- Workbox does not write the manifest or handle code-splitting — that is your bundler's job.
- It does not provide a push notification API — use the native Web Push API directly.
- Background sync in Workbox uses `BackgroundSyncPlugin`, which relies on the Background Sync API (not yet available in Safari as of this writing).

## Practical checklist

- [ ] Pin Workbox to a specific major version (`workbox-routing@7`) — avoid floating `@latest` in production.
- [ ] Use `InjectManifest` if you need any custom routing or background sync logic in the worker.
- [ ] Use `workbox-window` in the page for clean registration, update prompts, and `skipWaiting` coordination.
- [ ] Add `ExpirationPlugin` to every `CacheFirst` route to bound cache growth.
- [ ] Test with DevTools → Application → Service Workers → "Update on reload" to exercise precache revision logic.

## Cross-references

- [Caching strategies](/reference/service-worker/caching-strategies/) — the five strategies Workbox implements
- [The Fetch event and routing](/reference/service-worker/fetch-event/) — the raw event Workbox abstracts
- [The update flow and skipWaiting](/reference/service-worker/update-skipwaiting/) — `workbox-window`'s `messageSkipWaiting()` wires this