Skip to content

Commit 626e2b1

Browse files
fix: service worker improvements for PWA reliability (#127)
1 parent 79b034d commit 626e2b1

13 files changed

Lines changed: 495 additions & 3323 deletions

backend/src/index.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,15 @@ app.all('/api/opencode/*', requireAuth, async (c) => {
269269
const isProduction = ENV.SERVER.NODE_ENV === 'production'
270270

271271
if (isProduction) {
272+
app.use('/*', async (c, next) => {
273+
await next()
274+
if (c.req.path === '/sw.js') {
275+
c.res.headers.set('Cache-Control', 'no-cache, no-store, must-revalidate')
276+
c.res.headers.set('Pragma', 'no-cache')
277+
c.res.headers.set('Expires', '0')
278+
}
279+
})
280+
272281
app.use('/*', serveStatic({ root: './frontend/dist' }))
273282

274283
app.get('*', async (c) => {

frontend/package.json

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,6 @@
7373
"typescript": "~5.9.3",
7474
"typescript-eslint": "^8.45.0",
7575
"vite": "^7.1.7",
76-
"vite-plugin-pwa": "^1.2.0",
77-
"vitest": "^3.2.4",
78-
"workbox-core": "^7.4.0",
79-
"workbox-window": "^7.4.0",
80-
"workbox-precaching": "^7.4.0"
76+
"vitest": "^3.2.4"
8177
}
8278
}
83 Bytes
Loading
75 Bytes
Loading
499 Bytes
Loading
52 Bytes
Loading
562 Bytes
Loading

frontend/public/manifest.json

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,6 @@
2424
"src": "/icons/icon-512x512.png",
2525
"sizes": "512x512",
2626
"type": "image/png"
27-
},
28-
{
29-
"src": "/icons/icon-maskable-192x192.png",
30-
"sizes": "192x192",
31-
"type": "image/png",
32-
"purpose": "maskable"
33-
},
34-
{
35-
"src": "/icons/icon-maskable-512x512.png",
36-
"sizes": "512x512",
37-
"type": "image/png",
38-
"purpose": "maskable"
3927
}
4028
],
4129
"categories": ["developer", "productivity", "utilities"],

frontend/src/lib/serviceWorker.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
1+
import "../sw?worker";
2+
13
export function registerServiceWorker(): void {
24
if (!("serviceWorker" in navigator)) return;
3-
4-
navigator.serviceWorker
5-
.register("/sw.js", { scope: "/", type: "module" })
6-
.then((registration) => registration.update())
7-
.catch(() => {});
5+
navigator.serviceWorker.register("/sw.js", { scope: "/" }).catch(() => {});
86
}
97

108
export async function getServiceWorkerRegistration(): Promise<ServiceWorkerRegistration | null> {

frontend/src/sw.ts

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
11
/// <reference lib="webworker" />
2-
import { precacheAndRoute, cleanupOutdatedCaches } from "workbox-precaching";
32

4-
declare const self: ServiceWorkerGlobalScope & {
5-
__WB_MANIFEST: Array<{ url: string; revision: string | null }>;
6-
};
3+
declare const self: ServiceWorkerGlobalScope & typeof globalThis;
74

8-
cleanupOutdatedCaches();
9-
precacheAndRoute(self.__WB_MANIFEST);
5+
self.addEventListener("install", () => {
6+
self.skipWaiting();
7+
});
8+
9+
self.addEventListener("activate", (event) => {
10+
event.waitUntil(
11+
caches.keys().then((names) =>
12+
Promise.all(names.map((name) => caches.delete(name)))
13+
).then(() => self.clients.claim())
14+
);
15+
});
1016

1117
interface PushNotificationData {
1218
title: string;
@@ -22,15 +28,7 @@ interface PushNotificationData {
2228
};
2329
}
2430

25-
self.addEventListener("activate", (event) => {
26-
event.waitUntil(self.clients.claim());
27-
});
28-
29-
self.addEventListener("install", () => {
30-
self.skipWaiting();
31-
});
32-
33-
self.addEventListener("push", (event: PushEvent) => {
31+
self.addEventListener("push", (event) => {
3432
if (!event.data) return;
3533

3634
let payload: PushNotificationData;
@@ -56,7 +54,7 @@ self.addEventListener("push", (event: PushEvent) => {
5654
event.waitUntil(self.registration.showNotification(payload.title, options));
5755
});
5856

59-
self.addEventListener("notificationclick", (event: NotificationEvent) => {
57+
self.addEventListener("notificationclick", (event) => {
6058
event.notification.close();
6159

6260
const url = (event.notification.data?.url as string) ?? "/";
@@ -67,7 +65,7 @@ self.addEventListener("notificationclick", (event: NotificationEvent) => {
6765
.then((clientList) => {
6866
for (const client of clientList) {
6967
if (new URL(client.url).origin === self.location.origin) {
70-
client.focus();
68+
(client as WindowClient).focus();
7169
(client as WindowClient).navigate(url);
7270
return;
7371
}

0 commit comments

Comments
 (0)