How to use service workers for offline browsing

Australians expect useful sites to keep working when a train enters a tunnel, mobile coverage fades, or a regional connection becomes unreliable. A failed request can interrupt a booking, cart, map, news update, or work task. Offline support turns that fragility into a controlled fallback rather than a blank page.

A service worker is a JavaScript proxy between a web page and the network. Once registered, it can intercept requests, return saved responses, and refresh resources in the background. It does not make the internet faster by itself, but it reduces repeat downloads and provides a dependable route when a live request cannot complete.

The important distinction is control. Instead of mirroring the whole site indiscriminately, define a small application shell, identify public assets, and exclude private data. This creates useful offline pages without storing account records, one-time codes, or unlimited content on a device.

For developers, this is progressive enhancement: the normal online site remains intact, while the worker gains extra behaviour after registration. Core pages should open quickly, explain their offline state, and recover cleanly as connectivity returns.

What a service worker actually does

Registration starts from a page you control and must use HTTPS; localhost is also accepted for secure local development. Placing service-worker.js at the site root gives it the broadest practical default scope.

if ('serviceWorker' in navigator) {
  window.addEventListener('load', () => {
    navigator.serviceWorker.register('/service-worker.js');
  });
}

Use feature detection and handle registration failure without blocking rendering. Registration can run after the load event so it does not compete with the first visible content.

The install event precaches the chosen release, activate removes obsolete versions, and fetch decides how each request is answered. Because workers can stop between events, keep needed state in the Cache API or IndexedDB, not temporary variables.

The worker runs in a restricted context with self, has no page DOM, and returns promises through respondWith(). Unhandled requests continue to the network, which makes an online-first implementation easy to reason about.

Preparing the application shell

Treat the application shell as the minimum files needed to open a meaningful screen: HTML, critical CSS and JavaScript, icons, essential fonts, and layout data. A retailer might include catalogue pages and product images; a field-service tool might prioritise job details and address notes.

Give each release a cache name such as app-shell-v4. During installation, cache.addAll() is simple, but it rejects the whole batch if one required file fails. Fetch optional assets individually, and make missing images or fonts non-fatal to activation.

Set lifetimes according to content and sensitivity. Fingerprinted bundles can remain cached for a year, photographs can use a chosen period, and authentication or payment responses should stay network-only. The Cache API stores selected responses explicitly rather than following normal HTTP freshness rules.

Matching cache strategies to content

Use network-first for HTML navigations when fresh content matters. Fetch with a sensible timeout, cache a successful clone, and fall back to the cached shell after failure. This protects navigation without pretending that an offline price, booking, or stock count is current.

Use cache-first for fingerprinted assets because each URL represents an unchanged version. For optional content, stale-while-revalidate can return the saved copy immediately and refresh it for the next visit. Always clone a response before reading one version and storing another.

Treat API reads and writes separately. A public, read-only endpoint may have a short cache lifetime, but personal records should not cross that boundary. Queue offline writes only with visible status, conflict handling, and a retry action; Background Sync is an enhancement, not a universal delivery guarantee.

A practical offline caching checklist

A useful policy can be reduced to a few deliberate checks:

Files to precache

States to verify

These checks expose weak assumptions before customers do. During QA, record cache size, activation time, failed asset names, and fallback success. Repeat the tests with little free storage and terminate the worker between requests, since a persistent in-memory cache gives misleading results.

Managing updates and user feedback

Updates need an orderly lifecycle. Install a new versioned cache, wait until existing pages can move safely, activate the new worker, and delete caches used only by the old release. Calling skipWaiting() can mix old and new assets, so use it only when that risk is acceptable.

Allow the page to detect a waiting worker with registration.update() and show a restrained refresh message when appropriate. Preserve the current screen while the user continues. Repeated prompts are annoying, so remember a postponed choice for that release.

For forms, save drafts in IndexedDB, label unsent changes, and attempt delivery after reconnection. Confirm delivery only when evidence exists. Sensitive drafts need restricted storage, a short retention period, and clear deletion after submission or cancellation.

Testing Australian network conditions

Test beyond a fast office connection. In Sydney and Melbourne, users may pass through coverage gaps around tunnels, stations, and building basements. In regional and remote parts of Western Australia, the Northern Territory, and northern New South Wales, high latency or intermittent service can reveal timeouts hidden by city testing.

Simulate slow 3G, high latency, packet loss, and sudden offline transitions. Check current Chrome, Edge, Firefox, and Safari across desktop and mobile, because cache controls, update timing, and installation prompts differ. A site can support offline use without being installable as a progressive web app.

Australian retail campaigns such as Black Friday and Click Frenzy create another useful test period: navigation may survive congestion, but live prices and inventory must be marked as potentially stale. Measure real offline success, first cached render, storage rejection, update failure, and support complaints by network state.

Deployment, monitoring, and support

Deploy the worker and its shell with versioned filenames and sensible HTTP headers. Test the production domain over HTTPS, because a worker can behave differently under a preview host. Use the browser’s Application panel to inspect registrations, Cache Storage, activation, and termination.

Monitor registration errors, cache misses, storage quota failures, and unhandled fetch exceptions without logging personal page contents. Apply appropriate access controls and retention practices under the Australian Privacy Principles. A worker should never contain secrets in source code or preserve sensitive responses “just in case.”

Keep support and technical teams aligned on what remains available offline and what requires a live connection. For a business or media enquiry about resilient digital content, contact the SpeedTao team. Clear ownership and field feedback help a small, carefully cached experience stay dependable.