From 0404faa8566b457b190c3618dd65532ee3453bc9 Mon Sep 17 00:00:00 2001 From: Bram Kragten Date: Wed, 10 Mar 2021 05:33:11 +0100 Subject: [PATCH] Update serviceworker with catch handler (#8601) --- src/entrypoints/service_worker.ts | 47 +++++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 6 deletions(-) diff --git a/src/entrypoints/service_worker.ts b/src/entrypoints/service_worker.ts index cd536e7d18..058263e56c 100644 --- a/src/entrypoints/service_worker.ts +++ b/src/entrypoints/service_worker.ts @@ -2,15 +2,19 @@ // eslint-disable-next-line spaced-comment /// /* eslint-env serviceworker */ -import { cacheNames } from "workbox-core"; +import { cacheNames, RouteHandler } from "workbox-core"; import { cleanupOutdatedCaches, precacheAndRoute } from "workbox-precaching"; -import { registerRoute } from "workbox-routing"; +import { registerRoute, setCatchHandler } from "workbox-routing"; import { CacheFirst, NetworkOnly, StaleWhileRevalidate, } from "workbox-strategies"; +const noFallBackRegEx = new RegExp( + `${location.host}/(api|static|auth|frontend_latest|frontend_es5|local)/.*` +); + // Clean up caches from older workboxes and old service workers. // Will help with cleaning up Workbox v4 stuff cleanupOutdatedCaches(); @@ -18,13 +22,17 @@ cleanupOutdatedCaches(); function initRouting() { precacheAndRoute( // @ts-ignore - WB_MANIFEST + WB_MANIFEST, + { + // Ignore all URL parameters. + ignoreURLParametersMatching: [/.*/], + } ); // Cache static content (including translations) on first access. registerRoute( new RegExp(`${location.host}/(static|frontend_latest|frontend_es5)/.+`), - new CacheFirst() + new CacheFirst({ matchOptions: { ignoreSearch: true } }) ); // Get api from network. @@ -41,8 +49,14 @@ function initRouting() { new NetworkOnly() ); + // For the root "/" we ignore search + registerRoute( + new RegExp(`^${location.host}/(\\?.*)?$`), + new StaleWhileRevalidate({ matchOptions: { ignoreSearch: true } }) + ); + // For rest of the files (on Home Assistant domain only) try both cache and network. - // This includes the root "/" or "/states" response and user files from "/local". + // This includes "/states" response and user files from "/local". // First access might bring stale data from cache, but a single refresh will bring updated // file. registerRoute(new RegExp(`${location.host}/.*`), new StaleWhileRevalidate()); @@ -158,8 +172,15 @@ function initPushNotifications() { self.addEventListener("install", (event) => { // Delete all runtime caching, so that index.html has to be refetched. + // And add the new index.html back to the runtime cache const cacheName = cacheNames.runtime; - event.waitUntil(caches.delete(cacheName)); + event.waitUntil( + caches.delete(cacheName).then(() => + caches.open(cacheName).then((cache) => { + cache.add("/"); + }) + ) + ); }); self.addEventListener("activate", () => { @@ -177,5 +198,19 @@ self.addEventListener("message", (message) => { } }); +const catchHandler: RouteHandler = async (options) => { + const dest = (options.request as Request).destination; + const url = (options.request as Request).url; + + if (dest !== "document" || noFallBackRegEx.test(url)) { + return Response.error(); + } + // eslint-disable-next-line no-console + console.log("Using fallback for request:", options.request); + + return (await caches.match("/", { ignoreSearch: true })) || Response.error(); +}; + initRouting(); +setCatchHandler(catchHandler); initPushNotifications();