diff --git a/.eslintrc.json b/.eslintrc.json index 0909a15..ccdc4a8 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -67,5 +67,16 @@ "alphabetize": { "order": "asc", "caseInsensitive": true } } ] - } + }, + "overrides": [ + { + "files": ["service-worker.js"], + "rules": { + "no-restricted-globals": "off" + }, + "env": { + "serviceworker": true + } + } + ] } diff --git a/mamar-web/package.json b/mamar-web/package.json index 81cebb8..b8b3a3f 100644 --- a/mamar-web/package.json +++ b/mamar-web/package.json @@ -12,6 +12,7 @@ }, "dependencies": { "@adobe/react-spectrum": "^3.21.2", + "@parcel/service-worker": "^2.7.0", "@react-hook/resize-observer": "^1.2.6", "@spectrum-icons/workflow": "^4.0.2", "@types/stats.js": "^0.17.0", diff --git a/mamar-web/src/app/index.tsx b/mamar-web/src/app/index.tsx index 8de9174..df03a66 100644 --- a/mamar-web/src/app/index.tsx +++ b/mamar-web/src/app/index.tsx @@ -2,6 +2,7 @@ import * as WasmBridge from "mamar-wasm-bridge" import * as React from "react" import * as ReactDOM from "react-dom/client" +import "../service-worker-load.js" import report from "./analytics" import App from "./App" diff --git a/mamar-web/src/index.html b/mamar-web/src/index.html index 7f99439..ed99253 100644 --- a/mamar-web/src/index.html +++ b/mamar-web/src/index.html @@ -86,6 +86,7 @@

Contributing

diff --git a/mamar-web/src/service-worker-load.js b/mamar-web/src/service-worker-load.js new file mode 100644 index 0000000..e8f8f0f --- /dev/null +++ b/mamar-web/src/service-worker-load.js @@ -0,0 +1 @@ +navigator.serviceWorker.register(new URL("./service-worker.js", import.meta.url), { type: "module" }) diff --git a/mamar-web/src/service-worker.js b/mamar-web/src/service-worker.js new file mode 100644 index 0000000..14afc0e --- /dev/null +++ b/mamar-web/src/service-worker.js @@ -0,0 +1,33 @@ +import { manifest, version } from "@parcel/service-worker" + +async function install() { + const cache = await caches.open(version) + await cache.addAll(Array.from(new Set(manifest))) +} +addEventListener("install", evt => evt.waitUntil(install())) + +async function activate() { + const keys = await caches.keys() + await Promise.all( + keys.map(key => key !== version && caches.delete(key)), + ) +} +addEventListener("activate", evt => evt.waitUntil(activate())) + +addEventListener("fetch", evt => { + evt.respondWith((async () => { + const r = await caches.match(evt.request) + if (r) { + console.log("[service worker] Cache hit", evt.request.url) + return r + } + + console.error("[service worker] Cache miss", evt.request.url) + + const response = await fetch(evt.request) + const cache = await caches.open(version) + console.log(`[service worker] Caching new resource: ${evt.request.url}`) + cache.put(evt.request, response.clone()) + return response + })()) +}) diff --git a/yarn.lock b/yarn.lock index 376875c..6834668 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1862,6 +1862,11 @@ "@parcel/utils" "2.7.0" nullthrows "^1.1.1" +"@parcel/service-worker@^2.7.0": + version "2.7.0" + resolved "https://registry.yarnpkg.com/@parcel/service-worker/-/service-worker-2.7.0.tgz#b8525b2129cc21e33bc870c398a25cf9f5c31a12" + integrity sha512-EUMQcBtRQagZ4yVH2BxtToDpplLtfhjYqtvcgwVQIk3WkvMvKsTVCQZb9GHWKMBz7RKGdeQhbtZLPO3ywI0lfA== + "@parcel/source-map@^2.0.0": version "2.1.1" resolved "https://registry.yarnpkg.com/@parcel/source-map/-/source-map-2.1.1.tgz#fb193b82dba6dd62cc7a76b326f57bb35000a782"