Skip to content

Commit

Permalink
(fix) Service Worker Housekeeping: Remove Unused SW Events | Fix SW S…
Browse files Browse the repository at this point in the history
…tartup Cycle During Initial Load (#369)

* Removed the service worker's networkRequestFailed event infrastructure (as it became obsolete and is no longer used in any module).

* Remove unused variable.

* Ensure that the SW is responsible for new page registrations. Also clean up the offline setup and make it more robust (remove potential race-ish conditions).
  • Loading branch information
manuelroemer authored Mar 23, 2022
1 parent 4866c9e commit c103f2b
Show file tree
Hide file tree
Showing 7 changed files with 38 additions and 109 deletions.
18 changes: 0 additions & 18 deletions packages/framework/esm-offline/src/events.ts

This file was deleted.

2 changes: 0 additions & 2 deletions packages/framework/esm-offline/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
export * from "./service-worker";
export * from "./service-worker-http-headers";
export * from "./service-worker-messaging";
export * from "./service-worker-events";
export * from "./events";
export * from "./mode";
export * from "./patches";
export * from "./sync";
Expand Down
15 changes: 0 additions & 15 deletions packages/framework/esm-offline/src/service-worker-events.ts

This file was deleted.

85 changes: 33 additions & 52 deletions packages/shell/esm-app-shell/src/run.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { start, unregisterApplication, getAppNames } from "single-spa";
import { Workbox } from "workbox-window";
import {
setupApiModule,
renderLoadingSpinner,
Expand All @@ -18,11 +17,11 @@ import {
messageOmrsServiceWorker,
subscribeConnectivity,
getCurrentUser,
KnownOmrsServiceWorkerEvents,
dispatchNetworkRequestFailed,
renderModals,
dispatchPrecacheStaticDependencies,
activateOfflineCapability,
subscribePrecacheStaticDependencies,
openmrsFetch,
} from "@openmrs/esm-framework";
import {
finishRegisteringAllApps,
Expand Down Expand Up @@ -206,23 +205,16 @@ function showLoadingSpinner() {
return renderLoadingSpinner(document.body);
}

async function setupServiceWorker() {
const sw = await registerOmrsServiceWorker(
`${window.getOpenmrsSpaBase()}service-worker.js`
);

registerSwEvents(sw);

await prepareOfflineMode();
await activateOfflineCapability();
}

async function prepareOfflineMode() {
async function setupOffline() {
try {
await Promise.all([precacheImportMap(), precacheSharedApiEndpoints()]);
await registerOmrsServiceWorker(
`${window.getOpenmrsSpaBase()}service-worker.js`
);
await precacheImportMap();
await activateOfflineCapability();
setupOfflineStaticDependencyPrecaching();
} catch (e) {
console.error("Error while setting up offline mode.", e);

showNotification({
critical: true,
title: "Offline Setup Error",
Expand All @@ -231,21 +223,6 @@ async function prepareOfflineMode() {
}
}

function registerSwEvents(sw: Workbox) {
sw.addEventListener("message", (e) => {
const event = e.data as KnownOmrsServiceWorkerEvents;

if (event.type === "networkRequestFailed") {
dispatchNetworkRequestFailed(event);
} else {
console.warn(
`Received an unknown service worker event of type ${event.type}.`,
event
);
}
});
}

async function precacheImportMap() {
const importMap = await window.importMapOverrides.getCurrentPageMap();
await messageOmrsServiceWorker({
Expand All @@ -254,21 +231,6 @@ async function precacheImportMap() {
});
}

async function precacheSharedApiEndpoints() {
// By default, cache the session endpoint.
// This ensures that a lot of user/session related functions also work offline.
const sessionPathUrl = new URL(
`${window.openmrsBase}/ws/rest/v1/session`,
window.location.origin
).href;

await messageOmrsServiceWorker({
type: "registerDynamicRoute",
url: sessionPathUrl,
strategy: "network-first",
});
}

function setupOfflineStaticDependencyPrecaching() {
const precacheDelay = 1000 * 60 * 5;
let lastPrecache: Date | null = null;
Expand Down Expand Up @@ -302,6 +264,28 @@ function subscribeOnlineAndLoginChange(
});
}

async function precacheGlobalStaticDependencies() {
// By default, cache the session endpoint.
// This ensures that a lot of user/session related functions also work offline.
const sessionPathUrl = new URL(
`${window.openmrsBase}/ws/rest/v1/session`,
window.location.origin
).href;

await messageOmrsServiceWorker({
type: "registerDynamicRoute",
url: sessionPathUrl,
strategy: "network-first",
});

await openmrsFetch("/ws/rest/v1/session").catch((e) =>
console.warn(
"Failed to precache the user session data from the app shell. MFs depending on this data may run into problems while offline.",
e
)
);
}

function setupOfflineCssClasses() {
subscribeConnectivity(({ online }) => {
const body = document.querySelector("body")!;
Expand All @@ -324,20 +308,17 @@ export function run(configUrls: Array<string>, offline: boolean) {
createAppState({});
subscribeNotificationShown(showNotification);
subscribeToastShown(showToast);
subscribePrecacheStaticDependencies(precacheGlobalStaticDependencies);
registerModules(sharedDependencies);
setupApiModule();
registerCoreExtensions();

if (offline) {
setupServiceWorker();
}

return loadApps()
.then(setupApps)
.then(setupOfflineCssClasses)
.then(provideConfigs)
.then(runShell)
.catch(handleInitFailure)
.then(closeLoading)
.then(setupOfflineStaticDependencyPrecaching);
.then(() => (offline ? setupOffline() : undefined));
}
9 changes: 0 additions & 9 deletions packages/shell/esm-app-shell/src/service-worker/event.ts

This file was deleted.

5 changes: 5 additions & 0 deletions packages/shell/esm-app-shell/src/service-worker/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ setCacheNameDetails({ prefix: omrsCachePrefix });
registerAllOmrsRoutes();

self.addEventListener("message", handleMessage);

self.addEventListener("install", (e) => {
self.skipWaiting();

Expand All @@ -20,3 +21,7 @@ self.addEventListener("install", (e) => {
// If they change *during* a build, the SW is updated as well which triggers a re-installation.
e.waitUntil(precacheAppShell());
});

self.addEventListener("activate", (e) => {
e.waitUntil(self.clients.claim());
});
13 changes: 0 additions & 13 deletions packages/shell/esm-app-shell/src/service-worker/routing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,8 @@ import { validMethods } from "workbox-routing/utils/constants";
import { CacheOnly, NetworkFirst, NetworkOnly } from "workbox-strategies";
import { indexUrl, omrsCacheName } from "./constants";
import { ServiceWorkerDb } from "./storage";
import { publishEvent } from "./event";
import {
getOmrsHeader,
headersToObject,
parseOmrsOfflineResponseBodyHeader,
parseOmrsOfflineResponseStatusHeader,
} from "./http-header-utils";
Expand Down Expand Up @@ -78,7 +76,6 @@ async function navigationHandler(options: RouteHandlerCallbackOptions) {

async function defaultHandler(options: RouteHandlerCallbackOptions) {
const { request } = options;
const requestClone = await request.clone(); // Clone to avoid errors when calling request.text() later.
const handlerKey =
options.request.method === "GET"
? await getHandlerKey(options)
Expand All @@ -96,16 +93,6 @@ async function defaultHandler(options: RouteHandlerCallbackOptions) {
e
);

publishEvent({
type: "networkRequestFailed",
request: {
url: request.url,
method: request.method,
body: await requestClone.text(),
headers: headersToObject(request.headers),
},
});

return new Response(parseOmrsOfflineResponseBodyHeader(request.headers), {
status: parseOmrsOfflineResponseStatusHeader(request.headers),
});
Expand Down

0 comments on commit c103f2b

Please sign in to comment.