Skip to content

Precaching strategies: shipping the app shell ahead of time

Published

In one line: precaching stores a known, fixed set of files into the cache during the service worker’s install step, so the app shell is on the device before it is needed — the first navigation after install can render instantly and offline. It is the counterpart to runtime caching, which stores responses as the user requests them.

  • Precache — a fixed list known at build time (HTML shell, CSS, JS, icons, fonts). Fetched and stored during install, before the page asks for them. Suited to the app shell and other critical, always-needed assets.
  • Runtime cache — populated in the fetch handler as requests happen, under a chosen caching strategy. Suited to content that varies or is too large/numerous to list up front (API responses, user images, articles).

Precaching and runtime caching are complementary: precache the shell so the first load is fast and offline-capable, and runtime-cache the dynamic content around it.

  • Precache: the minimal app shell — the HTML/CSS/JS and icons needed to render a usable first screen. Everything listed here is downloaded and stored during the install event.
  • Runtime-cache instead: content that varies, is large, or is requested on demand is typically handled with a runtime caching strategy rather than being precached.

Precache the skeleton; let a runtime strategy handle the rest.

Why content revisioning is the core problem

Section titled “Why content revisioning is the core problem”

Precaching is only safe if the service worker can tell when a precached file has changed. If you precache /app.js and later deploy a new /app.js at the same URL, the service worker needs a signal that the content differs, or users keep the stale file.

Two ways to make change detectable:

  • Versioned URLs (/app.abc123.js): the URL itself changes when content changes, so the precache entry is naturally new. Workbox treats a URL that already carries versioning information (such as a content hash) as its own revision.
  • A revision per entry: pair each unversioned URL (like /index.html) with a content revision, so the cache refetches when the revision differs even though the URL is the same.

This bookkeeping is what a build-time precache manifest automates — maintaining it by hand is error-prone, which is why precaching is usually delegated to a library.

Workbox’s workbox-precaching module consumes a precache manifest (a list of { url, revision } entries, generated at build time) and handles the lifecycle for you:

  • During install, it fetches and stores every listed asset.
  • During activate, it removes entries from previous precaches that are no longer in the manifest, so old shell versions are cleaned up automatically.
  • It serves precached responses from the cache, and refetches an entry when its revision changes.
import { precacheAndRoute } from 'workbox-precaching';
// self.__WB_MANIFEST is injected at build time with { url, revision } entries.
precacheAndRoute(self.__WB_MANIFEST);

Workbox provides build tooling — workbox-build, the workbox-webpack-plugin, and the workbox-cli — to generate that precache manifest from your actual build output, so the list and revisions stay in sync with every deploy.

Precaching lives in the Cache Storage layer and is separate from the browser’s HTTP cache. The two can interact: a precache fetch may itself be served from the HTTP cache, which can land a stale copy in your precache. Where that risk matters, use versioned URLs so each version is a distinct request. Keep both layers’ lifetimes in mind so they don’t work against each other.

  • Precache only the minimal app shell; runtime-cache dynamic and large content.
  • Prefer versioned (hashed) URLs so changed assets are distinct requests.
  • For unversioned URLs (like /index.html), pair them with a content revision.
  • Generate the precache manifest at build time with Workbox tooling; don’t hand-maintain the list.
  • Rely on Workbox to clean up superseded precaches on activate.
  • Watch for HTTP-cache interactions that could precache a stale asset.