feat: implement per-route service worker selection
Updated the service worker registration logic to allow for specific service workers based on the route. Added support for a mobile service worker at `/m`, while maintaining existing functionality for `/counter` and `/new-order` routes. This enhances the PWA experience by serving optimized service workers for different app sections.
This commit is contained in:
parent
23d4e8dfe1
commit
bdd0ac46e3
2 changed files with 89 additions and 3 deletions
79
public/sw-mobile.js
Normal file
79
public/sw-mobile.js
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
// Service worker for the /m boss-dashboard PWA. Precaches the
|
||||
// mobile shell, network-first for navigations, never caches
|
||||
// boss-dashboard API responses (those are real-time glance data).
|
||||
const CACHE_NAME = "wfdash-mobile-v1";
|
||||
const OFFLINE_URL = "/offline";
|
||||
|
||||
const PRECACHE_ASSETS = [
|
||||
"/m",
|
||||
"/manifest-mobile.json",
|
||||
"/offline",
|
||||
"/android-chrome-192x192.png",
|
||||
"/android-chrome-512x512.png",
|
||||
"/apple-touch-icon.png",
|
||||
];
|
||||
|
||||
self.addEventListener("install", (event) => {
|
||||
event.waitUntil(
|
||||
caches.open(CACHE_NAME).then((cache) => cache.addAll(PRECACHE_ASSETS))
|
||||
);
|
||||
self.skipWaiting();
|
||||
});
|
||||
|
||||
self.addEventListener("activate", (event) => {
|
||||
event.waitUntil(
|
||||
caches.keys().then((keys) =>
|
||||
Promise.all(
|
||||
keys.filter((k) => k !== CACHE_NAME).map((k) => caches.delete(k))
|
||||
)
|
||||
)
|
||||
);
|
||||
self.clients.claim();
|
||||
});
|
||||
|
||||
self.addEventListener("fetch", (event) => {
|
||||
const { request } = event;
|
||||
if (request.method !== "GET") return;
|
||||
|
||||
const url = new URL(request.url);
|
||||
|
||||
// Never cache API traffic — boss-dashboard is real-time glance data
|
||||
// and serving a stale /api/v1/boss-dashboard or rep-activity would
|
||||
// actively mislead the boss.
|
||||
if (url.pathname.startsWith("/api/")) return;
|
||||
|
||||
// Navigation requests: network-first, fall back to the cached /m
|
||||
// shell, then the generic /offline page.
|
||||
if (request.mode === "navigate") {
|
||||
event.respondWith(
|
||||
fetch(request)
|
||||
.then((response) => {
|
||||
const clone = response.clone();
|
||||
caches.open(CACHE_NAME).then((cache) => cache.put(request, clone));
|
||||
return response;
|
||||
})
|
||||
.catch(async () => {
|
||||
const cached = await caches.match(request);
|
||||
if (cached) return cached;
|
||||
const mShell = await caches.match("/m");
|
||||
if (mShell) return mShell;
|
||||
return caches.match(OFFLINE_URL);
|
||||
})
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Static assets: stale-while-revalidate.
|
||||
event.respondWith(
|
||||
caches.match(request).then((cached) => {
|
||||
const networkFetch = fetch(request)
|
||||
.then((response) => {
|
||||
const clone = response.clone();
|
||||
caches.open(CACHE_NAME).then((cache) => cache.put(request, clone));
|
||||
return response;
|
||||
})
|
||||
.catch(() => cached);
|
||||
return cached || networkFetch;
|
||||
})
|
||||
);
|
||||
});
|
||||
|
|
@ -3,14 +3,21 @@
|
|||
import { useEffect } from "react";
|
||||
|
||||
/**
|
||||
* Counter PWA routes register `/sw-counter.js` (precaches /new-order
|
||||
* shell + manifest). Everything else keeps the main app's `/sw.js`.
|
||||
* Both SWs are scoped to `/` so co-existence is fine — they each
|
||||
* Per-route service-worker picker:
|
||||
* - /m → /sw-mobile.js (boss-dashboard PWA, dark theme)
|
||||
* - /counter → /sw-counter.js (over-the-counter order PWA)
|
||||
* - /new-order → /sw-counter.js (same counter PWA shell)
|
||||
* - everything else → /sw.js (main WFDASH app)
|
||||
*
|
||||
* All SWs are scoped to `/` so co-existence is fine — they each
|
||||
* cache their own URLs and ignore `/api/`.
|
||||
*/
|
||||
function pickSwPath(): string {
|
||||
if (typeof window === "undefined") return "/sw.js";
|
||||
const path = window.location.pathname;
|
||||
if (path === "/m" || path.startsWith("/m/")) {
|
||||
return "/sw-mobile.js";
|
||||
}
|
||||
if (path.startsWith("/counter") || path.startsWith("/new-order")) {
|
||||
return "/sw-counter.js";
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue