-
Notifications
You must be signed in to change notification settings - Fork 3.4k
Enable service worker for legacy build #21177
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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}`; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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,15 +79,20 @@ 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: { | ||
| privateFieldsAsProperties: true, | ||
| 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", | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How do these layers work, can't find anything about it in the webpack docs... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah the docs on it are quite sparse. It's more or less a tag/label for a module. You can assign it by entry like this, or via a condition in the module config. Then you can act on it in cache groups, by issuer layer in the module config (like I do here to change the loader options), and they also get grouped in the stats output. In this PR, it boils down to:
|
||
| } | ||
| : "./src/entrypoints/service-worker.ts", | ||
| app: "./src/entrypoints/app.ts", | ||
| authorize: "./src/entrypoints/authorize.ts", | ||
| onboarding: "./src/entrypoints/onboarding.ts", | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,93 +1,81 @@ | ||
| // 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'); | ||
| self.addEventListener('install', (event) => { | ||
| // This will activate the dev service worker, | ||
| // removing any prod service worker the dev might have running | ||
| self.skipWaiting(); | ||
| }); | ||
| ` | ||
| ); | ||
| done(); | ||
| }); | ||
| `.trim() + "\n"; | ||
steverep marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| 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-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", | ||
| }) | ||
| ) | ||
| ); | ||
| 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({ | ||
| // Files that mach this pattern will be considered unique and skip revision check | ||
| // ignore JS files + translation files | ||
| dontCacheBustURLsMatching: /(frontend_latest\/.+|static\/translations\/.+)/, | ||
|
|
||
| globDirectory: paths.app_output_root, | ||
| globPatterns: [ | ||
| "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 | ||
| // '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", | ||
| // Common fonts | ||
| "static/fonts/roboto/Roboto-Light.woff2", | ||
| "static/fonts/roboto/Roboto-Medium.woff2", | ||
| "static/fonts/roboto/Roboto-Regular.woff2", | ||
| "static/fonts/roboto/Roboto-Bold.woff2", | ||
| ], | ||
| }); | ||
|
|
||
| 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) | ||
| ); | ||
|
|
||
| // Write new file to root | ||
| fs.writeFileSync(swDest, serviceWorkerContent); | ||
| }); | ||
|
|
||
| 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") | ||
| ); | ||
| 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: new RegExp( | ||
| `(?:${buildDir}/.+|static/translations/.+)` | ||
| ), | ||
| globDirectory: paths.app_output_root, | ||
| globPatterns: [ | ||
| `${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' | ||
| "static/translations/**/en-+([a-fv0-9]).json", | ||
| // Icon shown on splash screen | ||
| "static/icons/favicon-192x192.png", | ||
| "static/icons/favicon.ico", | ||
| // Common fonts | ||
| "static/fonts/roboto/Roboto-Light.woff2", | ||
| "static/fonts/roboto/Roboto-Medium.woff2", | ||
| "static/fonts/roboto/Roboto-Regular.woff2", | ||
| "static/fonts/roboto/Roboto-Bold.woff2", | ||
| ], | ||
| globIgnores: [`${buildDir}/service-worker*`], | ||
| }); | ||
| if (warnings.length > 0) { | ||
| console.warn( | ||
| `Problems while injecting ${build} service worker:\n`, | ||
| warnings.join("\n") | ||
| ); | ||
| } | ||
| await deleteAsync(`${swSrc}?(.map)`); | ||
| }) | ||
| ) | ||
| ); | ||
Uh oh!
There was an error while loading. Please reload this page.