Skip to content

Commit 829ea72

Browse files
committed
chore: separate classic and module service worker registration
1 parent 32d20f0 commit 829ea72

File tree

4 files changed

+127
-18
lines changed

4 files changed

+127
-18
lines changed
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
// As of Dec 2024, Firefox does not support ES6 modules in service workers, so we need to use importScripts
2+
// https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorker#browser_compatibility
3+
importScripts("$(REMOTE_WEBAPP_PATH)$(REMOTE_BASE_PATH)/uno-config-script.js");
4+
5+
if (config.environmentVariables["UNO_BOOTSTRAP_DEBUGGER_ENABLED"] !== "True") {
6+
console.debug("[ServiceWorker] Initializing");
7+
let uno_enable_tracing = config.uno_enable_tracing;
8+
9+
self.addEventListener('install', function (e) {
10+
console.debug('[ServiceWorker] Installing offline worker');
11+
e.waitUntil(
12+
caches.open('$(CACHE_KEY)').then(async function (cache) {
13+
console.debug('[ServiceWorker] Caching app binaries and content');
14+
15+
// Add files one by one to avoid failed downloads to prevent the
16+
// worker to fail installing.
17+
for (var i = 0; i < config.offline_files.length; i++) {
18+
try {
19+
if (uno_enable_tracing) {
20+
console.debug(`[ServiceWorker] cache ${key}`);
21+
}
22+
23+
await cache.add(config.offline_files[i]);
24+
}
25+
catch (e) {
26+
console.debug(`[ServiceWorker] Failed to fetch ${config.offline_files[i]}`);
27+
}
28+
}
29+
30+
// Add the runtime's own files to the cache. We cannot use the
31+
// existing cached content from the runtime as the keys contain a
32+
// hash we cannot reliably compute.
33+
var c = await fetch("$(REMOTE_WEBAPP_PATH)_framework/blazor.boot.json");
34+
const monoConfigResources = (await c.json()).resources;
35+
36+
var entries = {
37+
...(monoConfigResources.coreAssembly || {})
38+
, ...(monoConfigResources.assembly || {})
39+
, ...(monoConfigResources.lazyAssembly || {})
40+
, ...(monoConfigResources.jsModuleWorker || {})
41+
, ...(monoConfigResources.jsModuleGlobalization || {})
42+
, ...(monoConfigResources.jsModuleNative || {})
43+
, ...(monoConfigResources.jsModuleRuntime || {})
44+
, ...(monoConfigResources.wasmNative || {})
45+
, ...(monoConfigResources.icu || {})
46+
, ...(monoConfigResources.coreAssembly || {})
47+
};
48+
49+
for (var key in entries) {
50+
var uri = `$(REMOTE_WEBAPP_PATH)_framework/${key}`;
51+
52+
if (uno_enable_tracing) {
53+
console.debug(`[ServiceWorker] cache ${uri}`);
54+
}
55+
56+
await cache.add(uri);
57+
}
58+
})
59+
);
60+
});
61+
62+
self.addEventListener('activate', event => {
63+
event.waitUntil(self.clients.claim());
64+
});
65+
66+
self.addEventListener('fetch', event => {
67+
event.respondWith(async function () {
68+
try {
69+
// Network first mode to get fresh content every time, then fallback to
70+
// cache content if needed.
71+
return await fetch(event.request);
72+
} catch (err) {
73+
return caches.match(event.request).then(response => {
74+
return response || fetch(event.request);
75+
});
76+
}
77+
}());
78+
});
79+
}
80+
else {
81+
// In development, always fetch from the network and do not enable offline support.
82+
// This is because caching would make development more difficult (changes would not
83+
// be reflected on the first load after each change).
84+
// It also breaks the hot reload feature because VS's browserlink is not always able to
85+
// inject its own framework in the served scripts and pages.
86+
self.addEventListener('fetch', () => { });
87+
}

src/Uno.Wasm.Bootstrap/Embedded/service-worker.js

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
// As of Dec 2024, Firefox does not support ES6 modules in service workers, so we need to use importScripts
2-
// https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorker#browser_compatibility
3-
importScripts("$(REMOTE_WEBAPP_PATH)$(REMOTE_BASE_PATH)/uno-config-script.js");
1+
import { config as unoConfig } from "$(REMOTE_WEBAPP_PATH)$(REMOTE_BASE_PATH)/uno-config.js";
42

5-
if (config.environmentVariables["UNO_BOOTSTRAP_DEBUGGER_ENABLED"] !== "True") {
3+
4+
if (unoConfig.environmentVariables["UNO_BOOTSTRAP_DEBUGGER_ENABLED"] !== "True") {
65
console.debug("[ServiceWorker] Initializing");
7-
let uno_enable_tracing = config.uno_enable_tracing;
6+
let uno_enable_tracing = unoConfig.uno_enable_tracing;
87

98
self.addEventListener('install', function (e) {
109
console.debug('[ServiceWorker] Installing offline worker');
@@ -14,16 +13,16 @@ if (config.environmentVariables["UNO_BOOTSTRAP_DEBUGGER_ENABLED"] !== "True") {
1413

1514
// Add files one by one to avoid failed downloads to prevent the
1615
// worker to fail installing.
17-
for (var i = 0; i < config.offline_files.length; i++) {
16+
for (var i = 0; i < unoConfig.offline_files.length; i++) {
1817
try {
1918
if (uno_enable_tracing) {
2019
console.debug(`[ServiceWorker] cache ${key}`);
2120
}
2221

23-
await cache.add(config.offline_files[i]);
22+
await cache.add(unoConfig.offline_files[i]);
2423
}
2524
catch (e) {
26-
console.debug(`[ServiceWorker] Failed to fetch ${config.offline_files[i]}`);
25+
console.debug(`[ServiceWorker] Failed to fetch ${unoConfig.offline_files[i]}`);
2726
}
2827
}
2928

src/Uno.Wasm.Bootstrap/ShellTask.cs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ public override bool Execute()
151151
RemoveDuplicateAssets();
152152
GeneratePackageFolder();
153153
BuildServiceWorker();
154+
BuildServiceWorkerClassic();
154155
GenerateEmbeddedJs();
155156
GenerateIndexHtml();
156157
GenerateConfig();
@@ -311,6 +312,24 @@ private void BuildServiceWorker()
311312
CopyStreamToOutput("service-worker.js", memoryStream, DeployMode.Root);
312313
}
313314

315+
// Case for browsers that do not support modules for service workers: Firefox for example
316+
private void BuildServiceWorkerClassic()
317+
{
318+
using var resourceStream = GetType().Assembly.GetManifestResourceStream("Uno.Wasm.Bootstrap.v0.Embedded.service-worker-classic.js");
319+
using var reader = new StreamReader(resourceStream);
320+
321+
var worker = TouchServiceWorker(reader.ReadToEnd());
322+
var memoryStream = new MemoryStream();
323+
324+
using var writer = new StreamWriter(memoryStream, Encoding.UTF8);
325+
writer.Write(worker);
326+
writer.Flush();
327+
328+
memoryStream.Position = 0;
329+
330+
CopyStreamToOutput("service-worker-classic.js", memoryStream, DeployMode.Root);
331+
}
332+
314333
private void ExtractAdditionalJS()
315334
{
316335
BuildResourceSearchList();
@@ -534,7 +553,8 @@ private void GenerateConfig()
534553
.Where(d =>
535554
!d.EndsWith("require.js")
536555
&& !d.EndsWith("uno-bootstrap.js")
537-
&& !d.EndsWith("service-worker.js"))
556+
&& !d.EndsWith("service-worker.js")
557+
&& !d.EndsWith("service-worker-classic.js"))
538558
.Select(dep => BuildDependencyPath(dep, baseLookup)));
539559

540560
var config = new StringBuilder();
@@ -636,7 +656,8 @@ private void GenerateConfigScript()
636656
.Where(d =>
637657
!d.EndsWith("require.js")
638658
&& !d.EndsWith("uno-bootstrap.js")
639-
&& !d.EndsWith("service-worker.js"))
659+
&& !d.EndsWith("service-worker.js")
660+
&& !d.EndsWith("service-worker-classic.js"))
640661
.Select(dep => BuildDependencyPath(dep, baseLookup)));
641662

642663
var config = new StringBuilder();

src/Uno.Wasm.Bootstrap/ts/Uno/WebAssembly/Bootstrapper.ts

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ namespace Uno.WebAssembly.Bootstrap {
259259

260260
this._runMain(this._unoConfig.uno_main, []);
261261

262-
this.initializePWA();
262+
await this.initializePWA();
263263

264264
} catch (e) {
265265
console.error(e);
@@ -510,7 +510,7 @@ namespace Uno.WebAssembly.Bootstrap {
510510
link.click();
511511
}
512512

513-
private initializePWA() {
513+
private async initializePWA(): Promise<void> {
514514

515515
if (typeof window === 'object' /* ENVIRONMENT_IS_WEB */) {
516516

@@ -522,15 +522,17 @@ namespace Uno.WebAssembly.Bootstrap {
522522

523523
console.debug(`Registering service worker for ${_webAppBasePath}`);
524524

525-
navigator.serviceWorker
526-
.register(
527-
`${_webAppBasePath}service-worker.js`, {
525+
try {
526+
await navigator.serviceWorker.register(`${_webAppBasePath}service-worker.js`, {
528527
scope: _webAppBasePath,
529528
type: 'module'
530-
})
531-
.then(function () {
532-
console.debug('Service Worker Registered');
533529
});
530+
console.debug('Service Worker Registered');
531+
} catch (e) {
532+
console.debug('Service Worker registration failed. falling back to classic service worker', e);
533+
534+
await navigator.serviceWorker.register(`${_webAppBasePath}service-worker-classic.js`, {scope: _webAppBasePath});
535+
}
534536
}
535537
}
536538
}

0 commit comments

Comments
 (0)