Versioned Service Worker
How Swoff versions service workers to prevent silent updates and give users control.
The Problem
Typical SW registration uses a fixed path like /sw.js. The browser automatically downloads and activates new versions on reload — dangerous if the update has breaking changes.
Swoff's Solution: Versioned Filenames
Instead of /sw.js, we use /sw-v1.0.0.js, /sw-v1.0.1.js, etc. Each version is a unique file that the browser only loads when you tell it to.
dist/
├── sw-v1.0.0.js ← Version 1.0.0
├── sw-v1.0.1.js ← Version 1.0.1
└── version.json ← Version manifestHow It Works
Version from package.json
{
"name": "my-app",
"version": "1.0.0"
}Build Generates Versioned SW
A build script reads the version from package.json, replaces placeholders in the SW template, and outputs a versioned SW file plus version.json. The script is straightforward string replacement — see Build Scripts for the implementation.
Client Checks version.json
On each load, the app fetches version.json and compares the version against the registered SW. If they differ, an update is available. See Client Registration for the implementation.
Update Flow
User opens app
↓
Fetch /version.json → Compare with localStorage['swRegisteredVersion']
↓
Same version? → Use existing SW
New version? → Fire 'sw-update-available' event → Show prompt
↓
User approves → Register new SW → Downloads assets → SKIP_WAITING → ReloadVersion Manifest
{
"version": "1.0.1",
"minSupportedVersion": "1.0.0",
"generatedAt": "2024-01-15T10:30:00.000Z"
}| Field | Purpose |
|---|---|
version | SemVer version string of this build |
minSupportedVersion | Minimum version users must have (enforced update) |
generatedAt | ISO timestamp of build |
Update Consent Flow
Users explicitly approve updates. The flow: idle → available → downloading → reload.
Minimum Supported Version (Forced Updates)
When releasing critical updates, set minSupportedVersion in swoff.config.json:
{
"minSupportedVersion": "1.0.5"
}If the user's registered version is less than minSupportedVersion, the update is mandatory — full-screen overlay with no dismiss option. Otherwise, it's optional (standard bottom-sheet).
Example: v1.0.5 is released with minSupportedVersion: "1.0.5" (security fix). v1.0.6 follows with minSupportedVersion: "1.0.5" (feature). A user on v1.0.4 visiting during v1.0.6 is forced to update because 1.0.4 < 1.0.5.
Users can dismiss optional updates for the current session via sessionStorage — see Client Registration for the implementation.
Events and Window Properties
| Event | Purpose |
|---|---|
sw-update-available | New version detected |
sw-progress | Download progress |
sw-ready | SW active |
interface Window {
latestSWVersion?: string;
currentSWVersion?: string;
swMinSupportedVersion?: string;
}Bumping Versions
npm version patch # 1.0.0 → 1.0.1
npm version minor # 1.0.0 → 1.1.0
npm version major # 1.0.0 → 2.0.0
npm run buildBenefits
- No silent updates — users explicitly approve
- Rollback possible — re-register the old version
- Clear versioning — filename shows exact version
- Browser agnostic — works in all browsers with SW support
Next Steps
- SW Template — the actual SW code
- Build Scripts — automating versioning
Swoff