Skip to content

Commit

Permalink
feat: enable offline support
Browse files Browse the repository at this point in the history
  • Loading branch information
czabaj committed Dec 20, 2024
1 parent 7062a0a commit f9861aa
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 10 deletions.
6 changes: 5 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,12 @@
"vite-plugin-ejs": "^1.7.0",
"vite-plugin-pwa": "^0.21.1",
"vitest": "^2.1.8",
"workbox-cacheable-response": "^7.3.0",
"workbox-core": "^7.3.0",
"workbox-precaching": "^7.3.0"
"workbox-expiration": "^7.3.0",
"workbox-precaching": "^7.3.0",
"workbox-routing": "^7.3.0",
"workbox-strategies": "^7.3.0"
},
"private": true,
"scripts": {
Expand Down
78 changes: 73 additions & 5 deletions src/serviceWorker/sw.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,60 @@
import { getMessaging, onBackgroundMessage } from "firebase/messaging/sw";
import { initializeApp } from "firebase/app";
import { CacheableResponsePlugin } from "workbox-cacheable-response";
import { clientsClaim } from "workbox-core";
import { cleanupOutdatedCaches, precacheAndRoute } from "workbox-precaching";
import { ExpirationPlugin } from "workbox-expiration";
import {
cleanupOutdatedCaches,
createHandlerBoundToURL,
precacheAndRoute,
} from "workbox-precaching";
import { NavigationRoute, registerRoute } from "workbox-routing";
import { NetworkFirst } from "workbox-strategies";

import { firebaseConfig } from "../backend/firebaseConfig";

declare const self: ServiceWorkerGlobalScope;

self.addEventListener("message", (event) => {
if (event.data && event.data.type === "SKIP_WAITING") self.skipWaiting();
});

self.skipWaiting();

clientsClaim();

const entries = self.__WB_MANIFEST;
if (import.meta.env.DEV) {
entries.push({ url: "/", revision: Math.random().toString() });
}
precacheAndRoute(entries);

cleanupOutdatedCaches();

precacheAndRoute(self.__WB_MANIFEST);
if (import.meta.env.PROD) {
// include webmanifest cache
registerRoute(
({ request, sameOrigin }) =>
sameOrigin && request.destination === "manifest",
new NetworkFirst({
cacheName: "webmanifest",
plugins: [
new CacheableResponsePlugin({ statuses: [200] }),
// we only need a few entries
new ExpirationPlugin({ maxEntries: 100 }),
],
})
);
}

self.addEventListener("message", (event) => {
if (event.data && event.data.type === "SKIP_WAITING") self.skipWaiting();
});
registerRoute(
new NavigationRoute(createHandlerBoundToURL("index.html"), {
denylist: [
/__\/auth\//, // exclude webmanifest: has its own cache
/^\/manifest-(.*).webmanifest$/,
],
})
);

const firebaseApp = initializeApp(firebaseConfig);
const messaging = getMessaging(firebaseApp);
Expand All @@ -26,5 +64,35 @@ onBackgroundMessage(messaging, (payload) => {
self.registration.showNotification(notificationTitle, {
body: payload.notification!.body,
icon: "/pwa-192.png",
data: { url: payload.fcmOptions?.link || "/" },
});
});

function findBestClient(clients: WindowClient[]) {
const focusedClient = clients.find((client) => client.focused);
const visibleClient = clients.find(
(client) => client.visibilityState === "visible"
);

return focusedClient || visibleClient || clients[0];
}

async function openUrl(url: string) {
const clients = await self.clients.matchAll({ type: "window" });
// Chrome 42-48 does not support navigate
if (clients.length !== 0 && "navigate" in clients[0]) {
const client = findBestClient(clients as WindowClient[]);
await client.navigate(url).then((client) => client?.focus());
}

await self.clients.openWindow(url);
}

self.addEventListener("notificationclick", (event) => {
const reactToNotificationClick = new Promise((resolve) => {
event.notification.close();
resolve(openUrl(event.notification.data.url || "/"));
});

event.waitUntil(reactToNotificationClick);
});
1 change: 1 addition & 0 deletions src/vite-env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/// <reference types="vite/client" />
8 changes: 4 additions & 4 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -8288,7 +8288,7 @@ workbox-build@^7.3.0:
workbox-sw "7.3.0"
workbox-window "7.3.0"

[email protected]:
[email protected], workbox-cacheable-response@^7.3.0:
version "7.3.0"
resolved "https://registry.yarnpkg.com/workbox-cacheable-response/-/workbox-cacheable-response-7.3.0.tgz#557b0f5fdfceb22fe243e3f19807c76a0ae646e3"
integrity sha512-eAFERIg6J2LuyELhLlmeRcJFa5e16Mj8kL2yCDbhWE+HUun9skRQrGIFVUagqWj4DMaaPSMWfAolM7XZZxNmxA==
Expand All @@ -8300,7 +8300,7 @@ [email protected], workbox-core@^7.3.0:
resolved "https://registry.yarnpkg.com/workbox-core/-/workbox-core-7.3.0.tgz#f24fb92041a0b7482fe2dd856544aaa9fa105248"
integrity sha512-Z+mYrErfh4t3zi7NVTvOuACB0A/jA3bgxUN3PwtAVHvfEsZxV9Iju580VEETug3zYJRc0Dmii/aixI/Uxj8fmw==

[email protected]:
[email protected], workbox-expiration@^7.3.0:
version "7.3.0"
resolved "https://registry.yarnpkg.com/workbox-expiration/-/workbox-expiration-7.3.0.tgz#2c1ee1fdada34aa7e7474f706d5429c914bd10d2"
integrity sha512-lpnSSLp2BM+K6bgFCWc5bS1LR5pAwDWbcKt1iL87/eTSJRdLdAwGQznZE+1czLgn/X05YChsrEegTNxjM067vQ==
Expand Down Expand Up @@ -8353,14 +8353,14 @@ [email protected]:
workbox-routing "7.3.0"
workbox-strategies "7.3.0"

[email protected]:
[email protected], workbox-routing@^7.3.0:
version "7.3.0"
resolved "https://registry.yarnpkg.com/workbox-routing/-/workbox-routing-7.3.0.tgz#fc86296bc1155c112ee2c16b3180853586c30208"
integrity sha512-ZUlysUVn5ZUzMOmQN3bqu+gK98vNfgX/gSTZ127izJg/pMMy4LryAthnYtjuqcjkN4HEAx1mdgxNiKJMZQM76A==
dependencies:
workbox-core "7.3.0"

[email protected]:
[email protected], workbox-strategies@^7.3.0:
version "7.3.0"
resolved "https://registry.yarnpkg.com/workbox-strategies/-/workbox-strategies-7.3.0.tgz#bb1530f205806895aacdea3639e6cf6bfb3a6cb0"
integrity sha512-tmZydug+qzDFATwX7QiEL5Hdf7FrkhjaF9db1CbB39sDmEZJg3l9ayDvPxy8Y18C3Y66Nrr9kkN1f/RlkDgllg==
Expand Down

0 comments on commit f9861aa

Please sign in to comment.