ServiceWorker
proxyっぽく間に挟まる感じ
何でも出来てしまうが、基本的にはネットワークから取得したデータをcacheする用途がメイン
あとはoffline対応
code:registerServiceWorker.ts
/// <reference no-default-lib="true" />
/// <reference lib="esnext" />
/// <reference lib="dom" />
await (async () => {
if (!("serviceWorker" in navigator)) return;
try {
const registration = await navigator.serviceWorker.register(
"sw.js",
{ scope: "/" } ,
);
if (registration.installing) {
console.log("Service worker installing");
} else if (registration.waiting) {
console.log("Service worker installed");
} else if (registration.active) {
console.log("Service worker active");
}
} catch (error: unknown) {
console.error(Registration failed with ${error});
}
})();
code:sw.ts
/// <reference no-default-lib="true" />
/// <reference lib="esnext" />
const cache = await globalThis.caches.open("v1");
workerのintall process
code:sw.ts
globalThis.addEventListener("install", (event) => {
event.waitUntil(
cache.addAll([
'/index.html',
'/style.css',
'/app.js',
'/image-list.js',
'/star-wars-logo.jpg',
'/gallery/bountyHunters.jpg',
'/gallery/myLittleVader.jpg',
'/gallery/snowTroopers.jpg',
]),
);
});
code:sw.ts
globalThis.addEventListener("activate", (event) => {
event.waitUntil(
globalThis.registration.navigationPreload?.enable?.()
);
});
code:sw.ts
globalThis.addEventListener("fetch", (event) => {
event.respondWith(
(async () => {
// First try to get the resource from the cache
const request = event.request;
const responseFromCache = await cache.match(request);
if (responseFromCache) return responseFromCache;
// Next try to use the preloaded response, if it's there
const preloadResponse = await event.preloadResponse;
if (preloadResponse) {
console.info("using preload response", preloadResponse);
await cache.put(request, preloadResponse.clone());
return preloadResponse;
}
// Next try to get the resource from the network
try {
const responseFromNetwork = await fetch(request);
// response may be used only once
// we need to save clone to put one copy in cache
// and serve second one
await cache.put(request, responseFromNetwork.clone());
return responseFromNetwork;
} catch (error: unknown) {
const fallbackUrl = "/gallery/myLittleVader.jpg";
const fallbackResponse = await caches.match(fallbackUrl);
if (fallbackResponse) return fallbackResponse;
// when even the fallback response is not available,
// there is nothing we can do, but we must always
// return a Response object
return new Response("Network error happened", {
status: 408,
headers: { "Content-Type": "text/plain" },
});
}
})()
);
});