feat: enhance service worker integration in web client

- Add message event listener in index.html to handle reload and update notifications from service worker - Implement loading flag and init function in service-worker.js to prevent multiple WASM initializations - Update status messages for better user feedback and fix HTML indentation for readability - Modify activate event to use new init function instead of direct runWASM call This improves the reliability and user experience of the web client by ensuring proper service worker communication and avoiding redundant operations.

lemon-mint committed Oct 31, 2025 at 18:43 UTC 9c908de8033ad9d253489ae13708d3d05dcd1c94
2 files changed +82 -47
cmd/webclient/index.html
+49 -38
@@ -1,46 +1,57 @@
1 <!DOCTYPE html>
2 <html>
3 -<head>
4 - <meta charset="UTF-8">
5 - <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 - <title>Portal Proxy</title>
7 -</head>
8 -<body>
9 - <h1>Portal Proxy</h1>
10 - <hr/>
11 - <p id="status">Please wait for the service worker to register...</p>
3 + <head>
4 + <meta charset="UTF-8">
5 + <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 + <title>Portal Proxy</title>
7 + </head>
8 + <body>
9 + <h1>Portal Proxy</h1>
10 + <hr/>
11 + <p id="status">Please wait for the service worker to register...</p>
12 + <script>
13 + async function registerServiceWorker() {
14 + try {
15 + if (!('serviceWorker'in navigator)) {
16 + throw new Error('This browser does not support Service Worker.');
17 + }
18
13 - <script>
14 - async function registerServiceWorker() {
15 - try {
16 - if (!('serviceWorker' in navigator)) {
17 - throw new Error('This browser does not support Service Worker.');
18 - }
19 + showStatus('Registering Service Worker...', 'loading');
20 +
21 + let reloadOnce = true;
22 +
23 + navigator.serviceWorker.addEventListener('message', (event) => {
24 + console.log(event.data);
25 + if (event.data && event.data.type === 'RELOAD_PAGE') {
26 + if (reloadOnce) {
27 + reloadOnce = false;
28 + window.location.reload();
29 + }
30 + }
31
20 - showStatus('Registering Service Worker...', 'loading');
21 -
22 - // Register service worker
23 - const registration = await navigator.serviceWorker.register('/service-worker.js', {
24 - scope: '/'
25 - });
26 - showStatus('Service Worker registered successfully', 'success');
32 + if (event.data && event.data.type === 'UPDATE_MSG') {
33 + showStatus(event.data.msg, 'info');
34 + }
35 + }
36 + );
37
28 - setTimeout(() => {
29 - showStatus('Reloading page...', 'loading');
30 - location.reload();
31 - }, 1000);
32 - } catch (error) {
33 - showStatus('Service Worker registration failed: ' + error.message, 'error');
38 + // Register service worker
39 + const registration = await navigator.serviceWorker.register('/service-worker.js', {
40 + scope: '/'
41 + });
42 + showStatus('Service Worker registered successfully, Wait a moment...', 'success');
43 + } catch (error) {
44 + showStatus('Service Worker registration failed: ' + error.message, 'error');
45 + }
46 }
35 - }
47
37 - function showStatus(message, status) {
38 - const statusElement = document.getElementById('status');
39 - statusElement.textContent = message;
40 - statusElement.className = status;
41 - }
48 + function showStatus(message, status) {
49 + const statusElement = document.getElementById('status');
50 + statusElement.textContent = message;
51 + statusElement.className = status;
52 + }
53
43 - registerServiceWorker();
44 - </script>
45 -</body>
46 -</html>
\ No newline at end of file
54 + registerServiceWorker();
55 + </script>
56 + </body>
57 +</html>
cmd/webclient/service-worker.js
+33 -9
@@ -1,9 +1,20 @@
1 // const wasm_exec_URL = "https://cdn.jsdelivr.net/gh/golang/go@go1.25.3/misc/wasm/wasm_exec.js";
2 -global = {};
2 const wasm_exec_URL = "/wasm_exec.js";
3 const wasm_URL = "/main.wasm";
4 importScripts(wasm_exec_URL);
5
6 +let loading = false;
7 +
8 +async function init() {
9 + if (loading) return;
10 + loading = true;
11 + try {
12 + await runWASM();
13 + } catch (error) {
14 + console.error("Error initializing WASM:", error);
15 + }
16 + loading = false;
17 +}
18
19 async function runWASM() {
20 const go = new Go();
@@ -31,28 +42,41 @@ self.addEventListener('install', (e) => {
42 e.waitUntil(LoadCache());
43 });
44
34 -self.addEventListener('activate', (e) => {
35 - async function Activate() {
36 - await runWASM();
37 - }
38 - e.waitUntil(Activate());
45 +async function sendMsg(data) {
46 + const clients = await self.clients.matchAll({ type: 'window' });
47 + clients.forEach(client => {
48 + client.postMessage({ type: 'RELOAD_PAGE' });
49 + });
50 +}
51 +
52 +self.addEventListener('activate', async (e) => {
53 + await sendMsg({ type: 'UPDATE_MSG', msg: 'Please wait while starting the WebAssembly module...' });
54 + await init();
55 + await self.clients.claim();
56 +
57 + setInterval(async () => {
58 + if (typeof __go_jshttp == 'undefined') return;
59 +
60 + console.log("Reloading page...")
61 + sendMsg({ type: 'RELOAD_PAGE' });
62 + }, 1000);
63 });
64
65 self.addEventListener('fetch', async (e) => {
66 console.log(e.request);
67
68 if (typeof __go_jshttp == 'undefined') {
45 - await runWASM();
69 + await init();
70 }
71
72 if (__go_jshttp) {
49 - e.respondWith((async () => {
73 + e.respondWith((async () => {
74 try {
75 const resp = await __go_jshttp(e.request);
76 return resp;
77 } catch {
78 __go_jshttp = undefined;
55 - await runWASM();
79 + await init();
80 const resp = await __go_jshttp(e.request);
81 return resp;
82 }