Skip to content

Commit 4def610

Browse files
committed
feat: improve caching
1 parent 4cf393b commit 4def610

1 file changed

Lines changed: 57 additions & 26 deletions

File tree

static/sw.js

Lines changed: 57 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1-
const CACHE_VERSION = "v18"; // Increment this when you have new features
1+
const CACHE_VERSION = "v19"; // Increment this when you have new features
22
const STATIC_CACHE = `andromeda-static-${CACHE_VERSION}`;
33
const DYNAMIC_CACHE = `andromeda-dynamic-${CACHE_VERSION}`;
44

5+
// Detect local development host where we don't want service worker caching
6+
const IS_LOCALHOST_DEV = (self.location && self.location.hostname === "localhost" && self.location.port === "8000");
7+
58
// Define what to cache
69
const STATIC_ASSETS = [
710
// Core pages
@@ -85,6 +88,12 @@ const CACHEABLE_PATTERNS = [
8588
// Install event - cache static assets
8689
self.addEventListener("install", (event) => {
8790
console.log("[SW] Installing service worker...");
91+
if (IS_LOCALHOST_DEV) {
92+
console.log("[SW] Detected localhost:8000 - skipping precache in dev mode");
93+
// Just skip waiting so dev reloads aren't blocked by precache
94+
event.waitUntil(self.skipWaiting());
95+
return;
96+
}
8897

8998
event.waitUntil(
9099
Promise.all([
@@ -144,23 +153,14 @@ self.addEventListener("install", (event) => {
144153
}
145154
}
146155

147-
// Cache discovered documentation pages
148-
return caches.open(DYNAMIC_CACHE)
149-
.then((cache) => {
150-
console.log(
151-
"[SW] Caching discovered documentation pages:",
152-
docUrls,
153-
);
154-
return Promise.allSettled(
155-
docUrls.map((url) =>
156-
fetch(url)
157-
.then((response) =>
158-
response.ok ? cache.put(url, response) : null
159-
)
160-
.catch(() => null)
161-
),
162-
);
163-
});
156+
// Cache discovered documentation pages (use cache helper)
157+
return Promise.allSettled(
158+
docUrls.map((url) =>
159+
fetch(url)
160+
.then((response) => (response.ok ? cacheIfAllowed(url, response) : null))
161+
.catch(() => null)
162+
),
163+
);
164164
})
165165
.catch(() =>
166166
console.log("[SW] Could not discover documentation pages")
@@ -215,15 +215,20 @@ self.addEventListener("fetch", (event) => {
215215
return;
216216
}
217217

218+
// If running on localhost:8000 during development, always go to network
219+
if (IS_LOCALHOST_DEV) {
220+
event.respondWith(fetch(request));
221+
return;
222+
}
223+
218224
// Network-first strategy for dynamic content
219225
if (NETWORK_FIRST.some((path) => url.pathname.startsWith(path))) {
220226
event.respondWith(
221227
fetch(request)
222228
.then((response) => {
223229
if (response.ok) {
224230
const responseClone = response.clone();
225-
caches.open(DYNAMIC_CACHE)
226-
.then((cache) => cache.put(request, responseClone));
231+
cacheIfAllowed(request, responseClone);
227232
}
228233
return response;
229234
})
@@ -246,8 +251,7 @@ self.addEventListener("fetch", (event) => {
246251
if (response.ok) {
247252
// Cache the fresh response
248253
const responseClone = response.clone();
249-
caches.open(DYNAMIC_CACHE)
250-
.then((cache) => cache.put(request, responseClone));
254+
cacheIfAllowed(request, responseClone);
251255
return response;
252256
}
253257

@@ -323,10 +327,7 @@ self.addEventListener("fetch", (event) => {
323327
const responseClone = response.clone();
324328

325329
// Cache the response
326-
caches.open(DYNAMIC_CACHE)
327-
.then((cache) => {
328-
cache.put(request, responseClone);
329-
});
330+
cacheIfAllowed(request, responseClone);
330331

331332
return response;
332333
})
@@ -344,6 +345,36 @@ self.addEventListener("fetch", (event) => {
344345
);
345346
});
346347

348+
// Trim cache helper
349+
async function trimCache(cacheName, maxItems) {
350+
const cache = await caches.open(cacheName);
351+
const keys = await cache.keys();
352+
if (keys.length > maxItems) {
353+
const deleteCount = keys.length - maxItems;
354+
for (let i = 0; i < deleteCount; i++) {
355+
await cache.delete(keys[i]);
356+
}
357+
}
358+
}
359+
360+
// Cache response helper: skip images, videos, fonts to avoid large caches
361+
async function cacheIfAllowed(request, response, cacheName = DYNAMIC_CACHE, maxItems = 50) {
362+
try {
363+
if (!response || !response.ok) return;
364+
const ct = (response.headers && response.headers.get && response.headers.get("content-type")) || "";
365+
if (ct.startsWith("image/") || ct.includes("video") || ct.includes("font") || ct.includes("audio")) {
366+
// skip caching large media files
367+
return;
368+
}
369+
const cache = await caches.open(cacheName);
370+
await cache.put(request, response.clone());
371+
await trimCache(cacheName, maxItems);
372+
} catch (e) {
373+
// Don't let caching failures break the response
374+
console.warn("[SW] cacheIfAllowed failed", e);
375+
}
376+
}
377+
347378
// Helper function to generate offline pages
348379
function generateOfflinePage(title, message) {
349380
return new Response(

0 commit comments

Comments
 (0)