SwoffSwoff

Precaching

Background activation-first precaching with IndexedDB checkpoint resume, progress reporting, and version-aware reset.

If you're coming from Workbox: Workbox blocks the install event until all assets are cached — the SW can't activate until precaching finishes. Swoff activates immediately and precaches in the background. If the SW is terminated mid-way, it resumes from the last checkpoint instead of starting over. See the comparison table below.

Status

On by default. After swoff init, the generated SW precaches all scanned build assets, navigation fallback pages, and the PWA manifest.

See the Precaching Architecture for the design rationale — background activation-first, checkpoint system, progress reporting, client-initiated resume, version-aware reset, and reset protocol.

What gets precached

Three sources feed into the ASSETS_TO_CACHE list:

SourceHow it's configuredExample
Build output directoriesbuild.precacheDirs.next/static/*/_next/static/*.js
Navigation fallback pagesserviceWorker.navigation.fallback + rules[].fallback/index.html, /offline.html
Explicit route listserviceWorker.navigation.precacheRoutes["/", "/about", "/blog"]
PWA manifestAutomatically included when features.pwa.enabled/manifest.json

All URLs are deduplicated at build time — if the same URL appears from multiple sources, it's only precached once.

Framework adapter

The useSwoffPrecache adapter exposes { progress } — a number from 0 to 100:

function PrecacheIndicator() {
  const { progress } = useSwoffPrecache();
  if (progress === 0 || progress === 100) return null;
  return <div>Precaching: {progress}%</div>;
}

If your framework already has this adapter (React, Vue, Svelte), the CLI generates it into swoff/adapters/. To create adapters for any other framework, see the Blueprint.

Config

{
  "features": {
    "serviceWorker": {
      "precache": {
        "concurrency": 3,
        "delayMs": 50
      }
    },
    "pwa": {
      "enabled": true
    }
  },
  "build": {
    "precacheDirs": {
      ".next/static": {
        "prefix": "/_next/static"
      }
    }
  }
}

features.serviceWorker.precache

FieldTypeDefaultDescription
concurrencynumber1Number of assets to download simultaneously in each batch. Higher values speed up large precaches but may increase bandwidth contention.
delayMsnumber0Delay in milliseconds between starting individual requests within a batch. Spaces out requests to avoid network saturation on initial load.

build.precacheDirs

Each key is a filesystem path relative to project root. See the Service Worker config for all options (prefix, matchExtensions, stripExtensions, stripSuffixes, excludeDirs, excludeFiles).

Comparison

AspectSwoffWorkboxSerwist
TimingAfter activate (background, non-blocking)During install (blocks activation)During install (blocks activation)
Install eventskipWaiting() only, zero downloadsDownloads all assets, blocks until completeDownloads all assets, blocks until complete
Checkpoint/resume✅ IndexedDB checkpoint — survives termination❌ Full re-download on SW restart❌ Full re-download on SW restart
Per-asset progress events✅ Built-in: SW_PROGRESSsw-progress DOM event🟡 Via workbox.progressReporting plugin🟡 Limited
Concurrency controlprecache.concurrency + precache.delayMs🟡 maxParallelRequests (plugin only)
Inter-request spacingdelayMs between requests in a batch
Client-initiated resume✅ Visibility change + online → RESUME_PRECACHE
Version-aware reset✅ Content hash of asset list; auto-reset on deploy🟡 Revision manifest mismatch🟡 Revision manifest mismatch
Full re-cache without re-registrationRESET_CACHE message via MessageChannel
Framework adaptersuseSwoffPrecache (14 frameworks)🟡 registerSW() only

On this page