mirror of https://github.com/VERT-sh/VERT.git
192 lines
4.2 KiB
JavaScript
192 lines
4.2 KiB
JavaScript
const CACHE_NAME = "vert-wasm-cache-v1";
|
|
|
|
const WASM_FILES = [
|
|
"/pandoc.wasm",
|
|
"https://cdn.jsdelivr.net/npm/@ffmpeg/core@0.12.10/dist/esm/ffmpeg-core.js",
|
|
"https://cdn.jsdelivr.net/npm/@ffmpeg/core@0.12.10/dist/esm/ffmpeg-core.wasm",
|
|
];
|
|
|
|
const WASM_URL_PATTERNS = [
|
|
/\/src\/lib\/workers\/.*\.js$/, // dev mode worker files
|
|
/\/assets\/.*worker.*\.js$/, // prod worker files
|
|
/magick.*\.wasm$/, // magick-wasm (unneeded?)
|
|
];
|
|
|
|
function shouldCacheUrl(url) {
|
|
const urlObj = new URL(url);
|
|
|
|
if (WASM_FILES.includes(urlObj.pathname) || WASM_FILES.includes(url)) {
|
|
return true;
|
|
}
|
|
|
|
return WASM_URL_PATTERNS.some(
|
|
(pattern) => pattern.test(urlObj.pathname) || pattern.test(url),
|
|
);
|
|
}
|
|
|
|
self.addEventListener("install", (event) => {
|
|
console.log("[SW] installing service worker");
|
|
|
|
event.waitUntil(
|
|
caches.open(CACHE_NAME).then((cache) => {
|
|
const staticFiles = WASM_FILES.filter((file) =>
|
|
file.startsWith("/"),
|
|
);
|
|
if (staticFiles.length > 0) {
|
|
console.log("[SW] pre-caching static files:", staticFiles);
|
|
return cache.addAll(staticFiles).catch((err) => {
|
|
console.warn("[SW] failed to pre-cache some files:", err);
|
|
});
|
|
}
|
|
}),
|
|
);
|
|
|
|
self.skipWaiting();
|
|
});
|
|
|
|
self.addEventListener("activate", (event) => {
|
|
event.waitUntil(
|
|
caches
|
|
.keys()
|
|
.then((cacheNames) => {
|
|
return Promise.all(
|
|
cacheNames.map((cacheName) => {
|
|
if (
|
|
cacheName !== CACHE_NAME &&
|
|
cacheName.startsWith("vert-wasm-cache")
|
|
) {
|
|
console.log("[SW] deleting old cache:", cacheName);
|
|
return caches.delete(cacheName);
|
|
}
|
|
}),
|
|
);
|
|
})
|
|
.then(() => {
|
|
return self.clients.claim();
|
|
}),
|
|
);
|
|
});
|
|
|
|
self.addEventListener("fetch", (event) => {
|
|
const request = event.request;
|
|
|
|
if (!shouldCacheUrl(request.url)) {
|
|
return; // Let the request go through normally if not a target URL
|
|
}
|
|
|
|
// else intercept request
|
|
event.respondWith(
|
|
caches.match(request).then((cachedResponse) => {
|
|
if (cachedResponse) {
|
|
console.log("[SW] serving from cache:", request.url);
|
|
return cachedResponse;
|
|
}
|
|
|
|
console.log("[SW] fetching and caching:", request.url);
|
|
return fetch(request)
|
|
.then((response) => {
|
|
if (!response.ok) {
|
|
console.warn(
|
|
"[SW] not caching failed response:",
|
|
response.status,
|
|
request.url,
|
|
);
|
|
return response;
|
|
}
|
|
|
|
const responseToCache = response.clone();
|
|
caches.open(CACHE_NAME).then((cache) => {
|
|
cache
|
|
.put(request, responseToCache)
|
|
.then(() => {
|
|
console.log(
|
|
"[SW] cached successfully:",
|
|
request.url,
|
|
);
|
|
})
|
|
.catch((err) => {
|
|
console.warn(
|
|
"[SW] failed to cache:",
|
|
request.url,
|
|
err,
|
|
);
|
|
});
|
|
});
|
|
|
|
return response;
|
|
})
|
|
.catch((err) => {
|
|
console.error("[SW] fetch failed for:", request.url, err);
|
|
throw err;
|
|
});
|
|
}),
|
|
);
|
|
});
|
|
|
|
self.addEventListener("message", (event) => {
|
|
if (!event.data) return;
|
|
const type = event.data.type;
|
|
|
|
if (type === "GET_CACHE_INFO") {
|
|
event.waitUntil(
|
|
caches.open(CACHE_NAME).then(async (cache) => {
|
|
const keys = await cache.keys();
|
|
let totalSize = 0;
|
|
const files = [];
|
|
|
|
for (const request of keys) {
|
|
try {
|
|
const response = await cache.match(request);
|
|
if (response) {
|
|
const blob = await response.blob();
|
|
const size = blob.size;
|
|
totalSize += size;
|
|
|
|
files.push({
|
|
url: request.url,
|
|
size: size,
|
|
type:
|
|
response.headers.get("content-type") ||
|
|
"unknown",
|
|
});
|
|
}
|
|
} catch (err) {
|
|
console.warn(
|
|
"[SW] failed to get info for cached file:",
|
|
request.url,
|
|
err,
|
|
);
|
|
}
|
|
}
|
|
|
|
event.ports[0].postMessage({
|
|
totalSize,
|
|
fileCount: files.length,
|
|
files,
|
|
});
|
|
}),
|
|
);
|
|
}
|
|
|
|
if (type === "CLEAR_CACHE") {
|
|
event.waitUntil(
|
|
caches
|
|
.delete(CACHE_NAME)
|
|
.then(() => {
|
|
console.log("[SW] cache cleared");
|
|
return caches.open(CACHE_NAME);
|
|
})
|
|
.then(() => {
|
|
event.ports[0].postMessage({ success: true });
|
|
})
|
|
.catch((err) => {
|
|
console.error("[SW] failed to clear cache:", err);
|
|
event.ports[0].postMessage({
|
|
success: false,
|
|
error: err.message,
|
|
});
|
|
}),
|
|
);
|
|
}
|
|
});
|