78 lines
2.6 KiB
JavaScript
78 lines
2.6 KiB
JavaScript
// Service worker for the Neuron PWA powered by engram-lang.
|
|
//
|
|
// Caching strategy:
|
|
// /pkg/ — WASM runtime files, cache-first (content-addressed, change on version bump)
|
|
// *.elc — compiled bytecode, stale-while-revalidate (instant load, background update)
|
|
//
|
|
// The WASM runtime is fetched once and cached indefinitely.
|
|
// Engram programs (.elc) are served from cache immediately, then refreshed in
|
|
// the background so the next load gets the newest version — no user action needed.
|
|
|
|
const CACHE_NAME = 'engram-v1';
|
|
const WASM_CACHE = 'engram-wasm-v1';
|
|
|
|
// Files to pre-cache during service worker installation.
|
|
const PRECACHE = [
|
|
'/pkg/el_wasm_bg.wasm',
|
|
'/pkg/el_wasm.js',
|
|
];
|
|
|
|
self.addEventListener('install', event => {
|
|
event.waitUntil(
|
|
caches.open(WASM_CACHE).then(cache => cache.addAll(PRECACHE))
|
|
);
|
|
// Take control immediately — don't wait for existing tabs to close.
|
|
self.skipWaiting();
|
|
});
|
|
|
|
self.addEventListener('fetch', event => {
|
|
const url = new URL(event.request.url);
|
|
|
|
// WASM runtime files: cache-first.
|
|
// These are large and rarely change; the version bump forces a new URL.
|
|
if (url.pathname.startsWith('/pkg/')) {
|
|
event.respondWith(
|
|
caches.match(event.request).then(cached =>
|
|
cached || fetch(event.request).then(response => {
|
|
caches.open(WASM_CACHE).then(cache =>
|
|
cache.put(event.request, response.clone())
|
|
);
|
|
return response;
|
|
})
|
|
)
|
|
);
|
|
return;
|
|
}
|
|
|
|
// Compiled bytecode (.elc): stale-while-revalidate.
|
|
// Respond immediately from cache, update in background.
|
|
if (url.pathname.endsWith('.elc')) {
|
|
event.respondWith(
|
|
caches.open(CACHE_NAME).then(async cache => {
|
|
const cached = await cache.match(event.request);
|
|
const fetchPromise = fetch(event.request).then(response => {
|
|
cache.put(event.request, response.clone());
|
|
return response;
|
|
});
|
|
return cached || fetchPromise;
|
|
})
|
|
);
|
|
return;
|
|
}
|
|
});
|
|
|
|
self.addEventListener('activate', event => {
|
|
// Purge old cache versions to reclaim storage.
|
|
event.waitUntil(
|
|
caches.keys().then(keys =>
|
|
Promise.all(
|
|
keys
|
|
.filter(k => k !== CACHE_NAME && k !== WASM_CACHE)
|
|
.map(k => caches.delete(k))
|
|
)
|
|
)
|
|
);
|
|
// Claim all clients immediately.
|
|
self.clients.claim();
|
|
});
|