How TREK's PWA Implementation Enables Offline Support with Service Workers
TREK enables offline support by registering a Service Worker that intercepts network requests, caches API responses and map tiles via the Cache API, and serves cached content when the device is offline, while providing mechanisms to clear sensitive data on logout and handle authentication updates.
TREK is an open-source trekking application built with modern web technologies that leverages Progressive Web App (PWA) capabilities to deliver a seamless offline-first experience. According to the TREK source code, the implementation combines a Service Worker generated by the Vite-PWA plugin with custom prefetching routines and cache management strategies to ensure users can access map data and core functionality without network connectivity.
Service Worker Registration and Initialization
The foundation of TREK's offline capability begins with Service Worker registration handled automatically by the Vite-PWA plugin. During application startup, the plugin calls navigator.serviceWorker.register() to install the sw.js file, which immediately begins intercepting network requests.
As implemented in the project's vite.config.js, this configuration generates a Service Worker that employs a Cache-First strategy for static assets. Once registered, the Service Worker acts as a network proxy, allowing the application to store and retrieve responses even when the device disconnects from the internet.
Prefetching Map Tiles for Offline Use
A critical component of TREK's offline support is the aggressive prefetching of map tiles before connectivity is lost. The prefetchTiles function in client/src/sync/tilePrefetcher.ts programmatically populates the Service Worker cache by fetching tiles within a specified geographic bounding box.
The function iterates through zoom levels from 10 to 16, calculates tile coordinates, and issues fetch requests with { mode: 'no-cors' }. Because the Service Worker intercepts these requests, the responses are automatically cached, making map data available offline:
// client/src/sync/tilePrefetcher.ts – prefetches map tiles into the SW cache
export async function prefetchTiles(
bbox: TileBbox,
tileUrlTemplate: string,
minZoom = 10,
maxZoom = 16,
): Promise<number> {
if (!navigator.onLine) return 0 // abort when offline
if (!('serviceWorker' in navigator) || !navigator.serviceWorker.controller) return 0
let fetched = 0
for (let z = minZoom; z <= maxZoom; z++) {
// compute tile coordinates …
for (let x = minX; x <= maxX; x++) {
for (let y = minY; y <= maxY; y++) {
const url = buildTileUrl(tileUrlTemplate, z, x, y)
fetch(url, { mode: 'no-cors' }).catch(() => {}) // SW caches the response
fetched++
}
}
}
return fetched
}
This approach ensures that users can browse previously viewed map regions without consuming additional bandwidth or requiring live connectivity.
Caching API Responses and Static Assets
Beyond map tiles, the Service Worker intercepts all API requests and static asset fetches, storing responses in the Cache API. This provides instant offline reads for previously accessed data, preventing "page not found" errors when users navigate through cached sections of the application.
Components throughout the application check navigator.onLine to determine connectivity status, allowing the UI to gracefully degrade to cached content when the network is unavailable. This offline-first architecture ensures the application shell and critical data remain accessible regardless of network conditions.
Security: Clearing Sensitive Caches on Logout
TREK implements strict cache hygiene to protect user privacy. When a user logs out, the authStore.logout() method explicitly deletes caches containing sensitive information, specifically the api-data and user-uploads stores:
// client/src/store/authStore.ts – clears SW caches on logout
if ('caches' in window) {
await Promise.all([
caches.delete('api-data').catch(() => {}),
caches.delete('user-uploads').catch(() => {}),
])
}
This ensures no private trekking data, user uploads, or authentication artifacts persist on the device after logout, maintaining security while preserving the benefits of offline caching during active sessions.
Handling Service Worker Updates and Authentication
Stale Service Workers can interfere with authentication flows by serving cached versions of the application shell. TREK addresses this through the unregisterSWAndReload() function in client/src/api/client.ts, which removes the Service Worker registration and forces a full page reload when authentication redirects are required:
// client/src/api/client.ts – removes the SW before a forced reload
async function unregisterSWAndReload(): Promise<void> {
try {
const reg = await navigator.serviceWorker?.getRegistration()
if (reg) await reg.unregister()
} catch { /* ignore */ }
window.location.reload()
}
This mechanism ensures that users always receive the latest application version when re-authenticating, preventing edge cases where the Service Worker might serve a stale shell that cannot properly handle authentication tokens.
Summary
- Service Worker Registration: TREK uses the Vite-PWA plugin to register
sw.jsat startup, establishing a Cache-First strategy for offline asset delivery. - Tile Prefetching: The
prefetchTilesfunction inclient/src/sync/tilePrefetcher.tsproactively caches map tiles usingno-corsfetches, enabling offline map viewing. - Offline Detection: Components check
navigator.onLineto determine connectivity status and serve cached content when offline. - Cache Security: The
authStore.logout()method clears sensitive caches (api-dataanduser-uploads) to protect user privacy. - Update Handling:
unregisterSWAndReload()inclient/src/api/client.tsremoves stale Service Workers during authentication failures to ensure fresh application shells.
Frequently Asked Questions
How does TREK prefetch map tiles for offline use?
TREK's prefetchTiles function in client/src/sync/tilePrefetcher.ts calculates tile coordinates for a geographic bounding box and zoom range (10-16), then issues fetch requests with { mode: 'no-cors' }. The Service Worker intercepts these requests and caches the responses, making map data available when the device goes offline.
What happens to cached data when a user logs out of TREK?
When a user logs out, the authStore.logout() method explicitly deletes the api-data and user-uploads caches using the Cache API. This ensures sensitive trekking data and user uploads do not persist on the device after the session ends.
Why does TREK unregister the Service Worker during authentication failures?
TREK unregisters the Service Worker via unregisterSWAndReload() in client/src/api/client.ts when authentication fails because the Service Worker might be serving a stale Single Page Application (SPA) shell. Removing the registration and reloading ensures the edge proxy can re-authenticate the user and serve the latest application version.
How does TREK detect offline status?
Components throughout the application check the navigator.onLine property to determine network connectivity. When the device is offline, the application continues to function using cached data from the Service Worker, avoiding "page not found" errors and maintaining usability.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →