Offline Capability & SW
Understanding offline capability and the service workers that make it possible.
What Offline Capability Means
Most developers think offline capability means "caching assets so the page loads without internet." That's incomplete. For Swoff, an offline-capable app ensures:
- Static assets & routes load — all HTML, CSS, JS, images served via Service Worker
- App logic runs — JavaScript executes in the browser
- Dynamic data handled intelligently — reads cached, mutations queued when offline
- Navigation works — all routes accessible without network
The Offline Spectrum
| Level | What Works | Example |
|---|---|---|
| None | Nothing without internet | Traditional server-rendered apps |
| Partial | Assets cached, but data needs network | Basic PWA with no local storage |
| App Shell | Assets + all routes offline, reads cached, mutations queued when offline | Swoff apps |
Why Most PWAs Fail at Offline
- Cache assets but not data — app loads, then crashes trying to fetch API
- Rely on runtime caching —
stale-while-revalidatedoesn't help if cache is empty - Don't version their SW — browser auto-updates break things silently
- Don't handle failed fetches — no fallback UI for missing data
What is a Service Worker?
A service worker (SW) is a JavaScript file that runs in the background, separate from your web page. It is the foundation of offline capability:
- Runs in the background — separate from the main thread
- Intercepts network requests — can serve cached responses
- No DOM access — communicates with your app via
postMessage - Persists after page close — stays alive until explicitly removed
- HTTPS required — except localhost for development
SW Lifecycle
Register → Install → Activate → Fetch- Register — Your app registers the SW
- Install — SW downloads and caches assets
- Activate — Old SW cleaned up, new SW takes over
- Fetch — Intercepts requests, serves from cache
The Problem with Default SW Behavior
Browsers automatically download new SW files when detected, install them in the background, and activate on the next reload. If your new SW has breaking changes, users get them without warning.
Swoff's Solution: Versioned SW Files
Instead of /sw.js, we use /sw-v1.0.0.js, /sw-v1.0.1.js, etc. Each version is a unique file. The browser only loads the version you tell it to.
package.json version: 1.0.0
↓
Build generates: sw-v1.0.0.js + version.json
↓
User visits app → App checks version.json
↓
Same version? → Use existing SW
New version? → Show update prompt → User approves → Register new versionSee Versioned SW System for implementation details.
Versioned App vs PWA Install
These are two completely different things that people confuse because both use the word "install":
PWA Install (User Experience)
Creates a shortcut on the user's device. The app opens in a standalone window without browser UI. This is purely cosmetic — it doesn't change what the app does.
App Version Update (Technical)
Replaces the code with a new version. This is functional — it changes what the app does.
| Aspect | PWA Install | App Version Update |
|---|---|---|
| What | Creates shortcut | Replaces code |
| Trigger | User chooses | Developer releases |
| Frequency | Once per device | Every release |
| Effect | UI changes | Functionality changes |
| Offline | Doesn't help | Makes it possible |
You can have an offline app without PWA install (user accesses via bookmark). You can have versioned updates without PWA. Swoff treats these as independent features — versioned updates are core, PWA is optional.
Key SW Events
| Event | Where | Purpose |
|---|---|---|
install | SW | Cache assets |
activate | SW | Clean up old caches |
fetch | SW | Intercept requests |
message | SW | Receive messages from client |
controllerchange | Client | SW changed |
Important Limitations
- SW can't access DOM — use
postMessageto communicate with the page - SW is terminated when idle — don't rely on persistent state
- SW scope is its location —
/sw.jscontrols all pages under/
Next Steps
- PWA & Browser APIs — the supporting stack
- Versioned SW System — how we prevent silent updates
Swoff