Enable service worker for legacy build (#21177)

pull/21433/head
Steve Repsher 2024-07-19 04:54:27 -04:00 committed by GitHub
parent 729a12af0c
commit 82d84de426
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 211 additions and 114 deletions

View File

@ -37,3 +37,9 @@ not dead
unreleased versions
last 7 years
> 0.05% and supports websockets
[legacy-sw]
# Same as legacy plus supports service workers
unreleased versions
last 7 years
> 0.05% and supports websockets and supports serviceworkers

View File

@ -0,0 +1,55 @@
diff --git a/build/inject-manifest.js b/build/inject-manifest.js
index 60e3d2bb51c11a19fbbedbad65e101082ec41c36..fed6026630f43f86e25446383982cf6fb694313b 100644
--- a/build/inject-manifest.js
+++ b/build/inject-manifest.js
@@ -104,7 +104,7 @@ async function injectManifest(config) {
replaceString: manifestString,
searchString: options.injectionPoint,
});
- filesToWrite[options.swDest] = source;
+ filesToWrite[options.swDest] = source.replace(url, encodeURI(upath_1.default.basename(destPath)));
filesToWrite[destPath] = map;
}
else {
diff --git a/build/lib/translate-url-to-sourcemap-paths.js b/build/lib/translate-url-to-sourcemap-paths.js
index 3220c5474eeac6e8a56ca9b2ac2bd9be48529e43..5f003879a904d4840529a42dd056d288fd213771 100644
--- a/build/lib/translate-url-to-sourcemap-paths.js
+++ b/build/lib/translate-url-to-sourcemap-paths.js
@@ -22,7 +22,7 @@ function translateURLToSourcemapPaths(url, swSrc, swDest) {
const possibleSrcPath = upath_1.default.resolve(upath_1.default.dirname(swSrc), url);
if (fs_extra_1.default.existsSync(possibleSrcPath)) {
srcPath = possibleSrcPath;
- destPath = upath_1.default.resolve(upath_1.default.dirname(swDest), url);
+ destPath = `${swDest}.map`;
}
else {
warning = `${errors_1.errors['cant-find-sourcemap']} ${possibleSrcPath}`;
diff --git a/src/inject-manifest.ts b/src/inject-manifest.ts
index 8795ddcaa77aea7b0356417e4bc4b19e2b3f860c..fcdc68342d9ac53936c9ed40a9ccfc2f5070cad3 100644
--- a/src/inject-manifest.ts
+++ b/src/inject-manifest.ts
@@ -129,7 +129,10 @@ export async function injectManifest(
searchString: options.injectionPoint!,
});
- filesToWrite[options.swDest] = source;
+ filesToWrite[options.swDest] = source.replace(
+ url!,
+ encodeURI(upath.basename(destPath)),
+ );
filesToWrite[destPath] = map;
} else {
// If there's no sourcemap associated with swSrc, a simple string
diff --git a/src/lib/translate-url-to-sourcemap-paths.ts b/src/lib/translate-url-to-sourcemap-paths.ts
index 072eac40d4ef5d095a01cb7f7e392a9e034853bd..f0bbe69e88ef3a415de18a7e9cb264daea273d71 100644
--- a/src/lib/translate-url-to-sourcemap-paths.ts
+++ b/src/lib/translate-url-to-sourcemap-paths.ts
@@ -28,7 +28,7 @@ export function translateURLToSourcemapPaths(
const possibleSrcPath = upath.resolve(upath.dirname(swSrc), url);
if (fse.existsSync(possibleSrcPath)) {
srcPath = possibleSrcPath;
- destPath = upath.resolve(upath.dirname(swDest), url);
+ destPath = `${swDest}.map`;
} else {
warning = `${errors['cant-find-sourcemap']} ${possibleSrcPath}`;
}

View File

@ -47,7 +47,7 @@ module.exports.emptyPackages = ({ latestBuild, isHassioBuild }) =>
module.exports.definedVars = ({ isProdBuild, latestBuild, defineOverlay }) => ({
__DEV__: !isProdBuild,
__BUILD__: JSON.stringify(latestBuild ? "latest" : "es5"),
__BUILD__: JSON.stringify(latestBuild ? "modern" : "legacy"),
__VERSION__: JSON.stringify(env.version()),
__DEMO__: false,
__SUPERVISOR__: false,
@ -79,7 +79,12 @@ module.exports.terserOptions = ({ latestBuild, isTestBuild }) => ({
sourceMap: !isTestBuild,
});
module.exports.babelOptions = ({ latestBuild, isProdBuild, isTestBuild }) => ({
module.exports.babelOptions = ({
latestBuild,
isProdBuild,
isTestBuild,
sw,
}) => ({
babelrc: false,
compact: false,
assumptions: {
@ -87,7 +92,7 @@ module.exports.babelOptions = ({ latestBuild, isProdBuild, isTestBuild }) => ({
setPublicClassFields: true,
setSpreadProperties: true,
},
browserslistEnv: latestBuild ? "modern" : "legacy",
browserslistEnv: latestBuild ? "modern" : `legacy${sw ? "-sw" : ""}`,
presets: [
[
"@babel/preset-env",
@ -215,7 +220,13 @@ module.exports.config = {
return {
name: "frontend" + nameSuffix(latestBuild),
entry: {
service_worker: "./src/entrypoints/service_worker.ts",
"service-worker":
!env.useRollup() && !latestBuild
? {
import: "./src/entrypoints/service-worker.ts",
layer: "sw",
}
: "./src/entrypoints/service-worker.ts",
app: "./src/entrypoints/app.ts",
authorize: "./src/entrypoints/authorize.ts",
onboarding: "./src/entrypoints/onboarding.ts",

View File

@ -1,19 +1,18 @@
// Generate service worker.
// Based on manifest, create a file with the content as service_worker.js
// Generate service workers
import fs from "fs-extra";
import { deleteAsync } from "del";
import gulp from "gulp";
import path from "path";
import sourceMapUrl from "source-map-url";
import workboxBuild from "workbox-build";
import { mkdir, readFile, writeFile } from "node:fs/promises";
import { join, relative } from "node:path";
import { injectManifest } from "workbox-build";
import paths from "../paths.cjs";
const swDest = path.resolve(paths.app_output_root, "service_worker.js");
const SW_MAP = {
[paths.app_output_latest]: "modern",
[paths.app_output_es5]: "legacy",
};
const writeSW = (content) => fs.outputFileSync(swDest, content.trim() + "\n");
gulp.task("gen-service-worker-app-dev", (done) => {
writeSW(
const SW_DEV =
`
console.debug('Service worker disabled in development');
@ -22,46 +21,39 @@ self.addEventListener('install', (event) => {
// removing any prod service worker the dev might have running
self.skipWaiting();
});
`
`.trim() + "\n";
gulp.task("gen-service-worker-app-dev", async () => {
await mkdir(paths.app_output_root, { recursive: true });
await Promise.all(
Object.values(SW_MAP).map((build) =>
writeFile(join(paths.app_output_root, `sw-${build}.js`), SW_DEV, {
encoding: "utf-8",
})
)
);
done();
});
gulp.task("gen-service-worker-app-prod", async () => {
// Read bundled source file
const bundleManifestLatest = fs.readJsonSync(
path.resolve(paths.app_output_latest, "manifest.json")
gulp.task("gen-service-worker-app-prod", () =>
Promise.all(
Object.entries(SW_MAP).map(async ([outPath, build]) => {
const manifest = JSON.parse(
await readFile(join(outPath, "manifest.json"), "utf-8")
);
let serviceWorkerContent = fs.readFileSync(
paths.app_output_root + bundleManifestLatest["service_worker.js"],
"utf-8"
);
// Delete old file from frontend_latest so manifest won't pick it up
fs.removeSync(
paths.app_output_root + bundleManifestLatest["service_worker.js"]
);
fs.removeSync(
paths.app_output_root + bundleManifestLatest["service_worker.js.map"]
);
// Remove ES5
const bundleManifestES5 = fs.readJsonSync(
path.resolve(paths.app_output_es5, "manifest.json")
);
fs.removeSync(paths.app_output_root + bundleManifestES5["service_worker.js"]);
fs.removeSync(
paths.app_output_root + bundleManifestES5["service_worker.js.map"]
);
const workboxManifest = await workboxBuild.getManifest({
const swSrc = join(paths.app_output_root, manifest["service-worker.js"]);
const buildDir = relative(paths.app_output_root, outPath);
const { warnings } = await injectManifest({
swSrc,
swDest: join(paths.app_output_root, `sw-${build}.js`),
injectionPoint: "__WB_MANIFEST__",
// Files that mach this pattern will be considered unique and skip revision check
// ignore JS files + translation files
dontCacheBustURLsMatching: /(frontend_latest\/.+|static\/translations\/.+)/,
dontCacheBustURLsMatching: new RegExp(
`(?:${buildDir}/.+|static/translations/.+)`
),
globDirectory: paths.app_output_root,
globPatterns: [
"frontend_latest/*.js",
`${buildDir}/*.js`,
// Cache all English translations because we catch them as fallback
// Using pattern to match hash instead of * to avoid caching en-GB
// 'v' added as valid hash letter because in dev we hash with 'dev'
@ -75,19 +67,15 @@ gulp.task("gen-service-worker-app-prod", async () => {
"static/fonts/roboto/Roboto-Regular.woff2",
"static/fonts/roboto/Roboto-Bold.woff2",
],
globIgnores: [`${buildDir}/service-worker*`],
});
for (const warning of workboxManifest.warnings) {
console.warn(warning);
}
// remove source map and add WB manifest
serviceWorkerContent = sourceMapUrl.removeFrom(serviceWorkerContent);
serviceWorkerContent = serviceWorkerContent.replace(
"WB_MANIFEST",
JSON.stringify(workboxManifest.manifestEntries)
if (warnings.length > 0) {
console.warn(
`Problems while injecting ${build} service worker:\n`,
warnings.join("\n")
);
// Write new file to root
fs.writeFileSync(swDest, serviceWorkerContent);
});
}
await deleteAsync(`${swSrc}?(.map)`);
})
)
);

View File

@ -63,14 +63,19 @@ const createWebpackConfig = ({
rules: [
{
test: /\.m?js$|\.ts$/,
use: {
use: (info) => ({
loader: "babel-loader",
options: {
...bundle.babelOptions({ latestBuild, isProdBuild, isTestBuild }),
...bundle.babelOptions({
latestBuild,
isProdBuild,
isTestBuild,
sw: info.issuerLayer === "sw",
}),
cacheDirectory: !isProdBuild,
cacheCompression: false,
},
},
}),
resolve: {
fullySpecified: false,
},
@ -235,6 +240,7 @@ const createWebpackConfig = ({
),
},
experiments: {
layers: true,
outputModule: true,
},
};

View File

@ -231,7 +231,6 @@
"rollup-plugin-visualizer": "5.12.0",
"serve-handler": "6.1.5",
"sinon": "18.0.0",
"source-map-url": "0.4.1",
"systemjs": "6.15.1",
"tar": "7.4.0",
"terser-webpack-plugin": "5.3.10",
@ -244,7 +243,7 @@
"webpack-manifest-plugin": "5.0.0",
"webpack-stats-plugin": "1.1.3",
"webpackbar": "6.0.1",
"workbox-build": "7.1.1"
"workbox-build": "patch:workbox-build@npm%3A7.1.1#~/.yarn/patches/workbox-build-npm-7.1.1-a854f3faae.patch"
},
"_comment": "Polymer 3.2 contained a bug, fixed in https://github.com/Polymer/polymer/pull/5569, add as patch",
"resolutions": {

View File

@ -72,7 +72,7 @@ function initialize(
);
}
if (__BUILD__ === "es5") {
if (__BUILD__ === "legacy") {
start = start.then(() => window.loadES5Adapter());
}

View File

@ -13,18 +13,16 @@ import {
StaleWhileRevalidate,
} from "workbox-strategies";
declare const __WB_MANIFEST__: Parameters<typeof precacheAndRoute>[0];
const noFallBackRegEx =
/\/(api|static|auth|frontend_latest|frontend_es5|local)\/.*/;
const initRouting = () => {
precacheAndRoute(
// @ts-ignore
WB_MANIFEST,
{
precacheAndRoute(__WB_MANIFEST__, {
// Ignore all URL parameters.
ignoreURLParametersMatching: [/.*/],
}
);
});
// Cache static content (including translations) on first access.
registerRoute(
@ -56,11 +54,8 @@ const initRouting = () => {
// Get api from network.
registerRoute(/\/(api|auth)\/.*/, new NetworkOnly());
// Get manifest, service worker, onboarding from network.
registerRoute(
/\/(service_worker.js|manifest.json|onboarding.html)/,
new NetworkOnly()
);
// Get manifest and onboarding from network.
registerRoute(/\/(?:manifest\.json|onboarding\.html)/, new NetworkOnly());
// For the root "/" we ignore search
registerRoute(

View File

@ -157,7 +157,7 @@ class HaConfigInfo extends LitElement {
)}
</span>
<span class="version">
${JS_VERSION}${JS_TYPE !== "latest" ? `${JS_TYPE}` : ""}
${JS_VERSION}${JS_TYPE !== "modern" ? `${JS_TYPE}` : ""}
</span>
</li>
</ul>

View File

@ -21,7 +21,7 @@ declare global {
/* eslint-disable no-var, no-redeclare */
var __DEV__: boolean;
var __DEMO__: boolean;
var __BUILD__: "latest" | "es5";
var __BUILD__: "modern" | "legacy";
var __VERSION__: string;
var __STATIC_PATH__: string;
var __BACKWARDS_COMPAT__: boolean;

View File

@ -16,7 +16,7 @@ export const getUrl = (
// if both module and JS provided, base url on frontend build
if (panelConfig.module_url && panelConfig.js_url) {
if (__BUILD__ === "latest") {
if (__BUILD__ === "modern") {
return {
type: "module",
url: panelConfig.module_url,

View File

@ -17,7 +17,7 @@ export const registerServiceWorker = async (
location.reload();
});
const reg = await navigator.serviceWorker.register("/service_worker.js");
const reg = await navigator.serviceWorker.register(`/sw-${__BUILD__}.js`);
if (!notifyUpdate || __DEV__ || __DEMO__) {
return;

View File

@ -9088,7 +9088,6 @@ __metadata:
serve-handler: "npm:6.1.5"
sinon: "npm:18.0.0"
sortablejs: "npm:1.15.2"
source-map-url: "npm:0.4.1"
stacktrace-js: "npm:2.0.2"
superstruct: "npm:2.0.2"
systemjs: "npm:6.15.1"
@ -9113,7 +9112,7 @@ __metadata:
webpack-stats-plugin: "npm:1.1.3"
webpackbar: "npm:6.0.1"
weekstart: "npm:2.0.0"
workbox-build: "npm:7.1.1"
workbox-build: "patch:workbox-build@npm%3A7.1.1#~/.yarn/patches/workbox-build-npm-7.1.1-a854f3faae.patch"
workbox-cacheable-response: "npm:7.1.0"
workbox-core: "npm:7.1.0"
workbox-expiration: "npm:7.1.0"
@ -13273,13 +13272,6 @@ __metadata:
languageName: node
linkType: hard
"source-map-url@npm:0.4.1":
version: 0.4.1
resolution: "source-map-url@npm:0.4.1"
checksum: 10/7fec0460ca017330568e1a4d67c80c397871f27d75b034e1117eaa802076db5cda5944659144d26eafd2a95008ada19296c8e0d5ec116302c32c6daa4e430003
languageName: node
linkType: hard
"source-map@npm:0.5.6":
version: 0.5.6
resolution: "source-map@npm:0.5.6"
@ -15185,6 +15177,51 @@ __metadata:
languageName: node
linkType: hard
"workbox-build@patch:workbox-build@npm%3A7.1.1#~/.yarn/patches/workbox-build-npm-7.1.1-a854f3faae.patch":
version: 7.1.1
resolution: "workbox-build@patch:workbox-build@npm%3A7.1.1#~/.yarn/patches/workbox-build-npm-7.1.1-a854f3faae.patch::version=7.1.1&hash=cd5737"
dependencies:
"@apideck/better-ajv-errors": "npm:^0.3.1"
"@babel/core": "npm:^7.24.4"
"@babel/preset-env": "npm:^7.11.0"
"@babel/runtime": "npm:^7.11.2"
"@rollup/plugin-babel": "npm:^5.2.0"
"@rollup/plugin-node-resolve": "npm:^15.2.3"
"@rollup/plugin-replace": "npm:^2.4.1"
"@rollup/plugin-terser": "npm:^0.4.3"
"@surma/rollup-plugin-off-main-thread": "npm:^2.2.3"
ajv: "npm:^8.6.0"
common-tags: "npm:^1.8.0"
fast-json-stable-stringify: "npm:^2.1.0"
fs-extra: "npm:^9.0.1"
glob: "npm:^7.1.6"
lodash: "npm:^4.17.20"
pretty-bytes: "npm:^5.3.0"
rollup: "npm:^2.43.1"
source-map: "npm:^0.8.0-beta.0"
stringify-object: "npm:^3.3.0"
strip-comments: "npm:^2.0.1"
tempy: "npm:^0.6.0"
upath: "npm:^1.2.0"
workbox-background-sync: "npm:7.1.0"
workbox-broadcast-update: "npm:7.1.0"
workbox-cacheable-response: "npm:7.1.0"
workbox-core: "npm:7.1.0"
workbox-expiration: "npm:7.1.0"
workbox-google-analytics: "npm:7.1.0"
workbox-navigation-preload: "npm:7.1.0"
workbox-precaching: "npm:7.1.0"
workbox-range-requests: "npm:7.1.0"
workbox-recipes: "npm:7.1.0"
workbox-routing: "npm:7.1.0"
workbox-strategies: "npm:7.1.0"
workbox-streams: "npm:7.1.0"
workbox-sw: "npm:7.1.0"
workbox-window: "npm:7.1.0"
checksum: 10/321a4f8d914ff3c1ac36e447d0c48e99d8925f4cdcff8332722c9273e93948f5a429de692149039622ce275cab454d6ba84144f9ae00a912b44b5d65f80695cc
languageName: node
linkType: hard
"workbox-cacheable-response@npm:7.1.0":
version: 7.1.0
resolution: "workbox-cacheable-response@npm:7.1.0"