Clean up service worker code and fix 404 (#5855)

pull/5859/head
Paulus Schoutsen 2020-05-13 13:17:47 -07:00 committed by GitHub
parent 86bbac430c
commit 2153bc536c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 70 additions and 58 deletions

View File

@ -19,6 +19,8 @@ gulp.task("gen-service-worker-app-dev", (done) => {
console.debug('Service worker disabled in development');
self.addEventListener('install', (event) => {
// This will activate the dev service worker,
// removing any prod service worker the dev might have running
self.skipWaiting();
});
`
@ -27,6 +29,17 @@ self.addEventListener('install', (event) => {
});
gulp.task("gen-service-worker-app-prod", async () => {
// Read bundled source file
const bundleManifest = require(path.resolve(paths.output, "manifest.json"));
let serviceWorkerContent = fs.readFileSync(
paths.root + bundleManifest["service_worker.js"],
"utf-8"
);
// Delete old file from frontend_latest so manifest won't pick it up
fs.removeSync(paths.root + bundleManifest["service_worker.js"]);
fs.removeSync(paths.root + bundleManifest["service_worker.js.map"]);
const workboxManifest = await workboxBuild.getManifest({
// Files that mach this pattern will be considered unique and skip revision check
// ignore JS files + translation files
@ -37,7 +50,8 @@ gulp.task("gen-service-worker-app-prod", async () => {
"frontend_latest/*.js",
// Cache all English translations because we catch them as fallback
// Using pattern to match hash instead of * to avoid caching en-GB
"static/translations/**/en-+([a-f0-9]).json",
// 'v' added as valid hash letter because in dev we hash with 'dev'
"static/translations/**/en-+([a-fv0-9]).json",
// Icon shown on splash screen
"static/icons/favicon-192x192.png",
"static/icons/favicon.ico",
@ -53,20 +67,6 @@ gulp.task("gen-service-worker-app-prod", async () => {
console.warn(warning);
}
// Replace `null` with 0 for better compression
for (const entry of workboxManifest.manifestEntries) {
if (entry.revision === null) {
entry.revision = 0;
}
}
const manifest = require(path.resolve(paths.output, "manifest.json"));
// Write bundled source file
let serviceWorkerContent = fs.readFileSync(
paths.root + manifest["service_worker.js"],
"utf-8"
);
// remove source map and add WB manifest
serviceWorkerContent = sourceMapUrl.removeFrom(serviceWorkerContent);
serviceWorkerContent = serviceWorkerContent.replace(
@ -76,8 +76,4 @@ gulp.task("gen-service-worker-app-prod", async () => {
// Write new file to root
fs.writeFileSync(swDest, serviceWorkerContent);
// Delete old file from frontend_latest
fs.removeSync(paths.root + manifest["service_worker.js"]);
fs.removeSync(paths.root + manifest["service_worker.js.map"]);
});

View File

@ -184,7 +184,7 @@ export class HcConnect extends LitElement {
this.castManager = null;
}
);
registerServiceWorker(false);
registerServiceWorker(this, false);
}
private async _handleDemo() {

View File

@ -121,7 +121,7 @@ class HaAuthorize extends litLocalizeLiteMixin(LitElement) {
const tempA = document.createElement("a");
tempA.href = this.redirectUri!;
if (tempA.host === location.host) {
registerServiceWorker(false);
registerServiceWorker(this, false);
}
}

View File

@ -164,10 +164,18 @@ self.addEventListener("install", (event) => {
event.waitUntil(caches.delete(cacheName));
});
self.addEventListener("activate", () => {
// Attach the service worker to any page of the app
// that didn't have a service worker loaded.
// Happens the first time they open the app without any
// service worker registered.
// This will serve code splitted bundles from SW.
clients.claim();
});
self.addEventListener("message", (message) => {
if (message.data.type === "skipWaiting") {
self.skipWaiting();
clients.claim();
}
});

View File

@ -46,7 +46,7 @@ export class HomeAssistantAppEl extends HassElement {
protected firstUpdated(changedProps) {
super.firstUpdated(changedProps);
this._initialize();
setTimeout(registerServiceWorker, 1000);
setTimeout(() => registerServiceWorker(this), 1000);
/* polyfill for paper-dropdown */
import(
/* webpackChunkName: "polyfill-web-animations-next" */ "web-animations-js/web-animations-next-lite.min"

View File

@ -96,7 +96,7 @@ class HaOnboarding extends litLocalizeLiteMixin(HassElement) {
import(
/* webpackChunkName: "onboarding-core-config" */ "./onboarding-core-config"
);
registerServiceWorker(false);
registerServiceWorker(this, false);
this.addEventListener("onboarding-step", (ev) => this._handleStepDone(ev));
}

View File

@ -1,49 +1,57 @@
import { HassElement } from "../state/hass-element";
import { showToast } from "./toast";
export const supportsServiceWorker = () =>
"serviceWorker" in navigator &&
(location.protocol === "https:" || location.hostname === "localhost");
export const registerServiceWorker = (notifyUpdate = true) => {
export const registerServiceWorker = async (
rootEl: HTMLElement,
notifyUpdate = true
) => {
if (!supportsServiceWorker()) {
return;
}
navigator.serviceWorker.register("/service_worker.js").then((reg) => {
reg.addEventListener("updatefound", () => {
const installingWorker = reg.installing;
if (!installingWorker || !notifyUpdate) {
return;
}
installingWorker.addEventListener("statechange", () => {
if (
installingWorker.state === "installed" &&
navigator.serviceWorker.controller &&
!__DEV__ &&
!__DEMO__
) {
// Notify users here of a new frontend being available.
const haElement = window.document.querySelector(
"home-assistant, ha-onboarding"
)! as HassElement;
showToast(haElement, {
message: "A new version of the frontend is available.",
action: {
action: () =>
installingWorker.postMessage({ type: "skipWaiting" }),
text: "reload",
},
duration: 0,
dismissable: false,
});
}
});
});
});
// If the active service worker changes, refresh the page because the cache has changed
navigator.serviceWorker.addEventListener("controllerchange", () => {
location.reload();
});
const reg = await navigator.serviceWorker.register("/service_worker.js");
if (!notifyUpdate || __DEV__ || __DEMO__) {
return;
}
reg.addEventListener("updatefound", () => {
const installingWorker = reg.installing;
if (!installingWorker) {
return;
}
installingWorker.addEventListener("statechange", () => {
if (
installingWorker.state !== "installed" ||
!navigator.serviceWorker.controller
) {
return;
}
// Notify users a new frontend is available.
// When
showToast(rootEl, {
message: "A new version of the frontend is available.",
action: {
// We tell the service worker to call skipWaiting, which activates
// the new service worker. Above we listen for `controllerchange`
// so we reload the page once a new servic worker activates.
action: () => installingWorker.postMessage({ type: "skipWaiting" }),
text: "reload",
},
duration: 0,
dismissable: false,
});
});
});
};