wasm: remove unnecessary manifest parsing
Kim committed
Nov 17, 2025 at 11:02 UTC
a9c5f3b5fac5427c0d89428ee9df7f627a7578a5
2 files changed
+57
-88
cmd/relay-server/frontend.go
+2
-69
@@ -3,7 +3,6 @@ package main
3
import (
4
"embed"
5
"encoding/json"
6
- "fmt"
6
"net/http"
7
pathpkg "path"
8
"strconv"
@@ -515,69 +514,6 @@ func serveDynamicServiceWorker(w http.ResponseWriter, r *http.Request) {
514
return
515
}
516
518
- // Find the content-addressed WASM file
519
- wasmCacheMu.RLock()
520
- var wasmHash string
521
- var wasmFile string
522
- for filename, entry := range wasmCache {
523
- wasmHash = entry.hash
524
- wasmFile = filename
525
- break
526
- }
527
- wasmCacheMu.RUnlock()
528
-
529
- // Fallback: scan embedded WASM directory if cache is empty
530
- if wasmHash == "" {
531
- entries, err := wasmFS.ReadDir("dist")
532
- if err == nil {
533
- for _, entry := range entries {
534
- if entry.IsDir() {
535
- continue
536
- }
537
- name := entry.Name()
538
- if strings.HasSuffix(name, ".wasm.br") && len(name) == 72 {
539
- hash := strings.TrimSuffix(name, ".wasm.br")
540
- if isHexString(hash) && len(hash) == 64 {
541
- wasmHash = hash
542
- wasmFile = hash + ".wasm"
543
- break
544
- }
545
- }
546
- }
547
- }
548
- }
549
-
550
- // Generate WASM URL
551
- wasmURL := portalUIURL + "/frontend/" + wasmFile
552
-
553
- // Create manifest object
554
- manifestData := map[string]string{
555
- "wasmFile": wasmFile,
556
- "wasmUrl": wasmURL,
557
- "hash": wasmHash,
558
- "bootstraps": bootstrapURIs,
559
- }
560
-
561
- // Convert manifest to JSON string
562
- manifestJSON, err := json.Marshal(manifestData)
563
- if err != nil {
564
- log.Error().Err(err).Msg("Failed to marshal manifest for service worker")
565
- http.Error(w, "Internal server error", http.StatusInternalServerError)
566
- return
567
- }
568
-
569
- // Replace placeholders
570
- result := string(content)
571
- result = strings.ReplaceAll(result, "<PORTAL_UI_URL>", portalUIURL)
572
- result = strings.ReplaceAll(result, "\"<WASM_MANIFEST>\"", string(manifestJSON))
573
-
574
- // Inject __BOOTSTRAP_SERVERS__ as a global variable in service worker
575
- bootstrapServersLine := fmt.Sprintf("self.__BOOTSTRAP_SERVERS__ = %q;\n", bootstrapURIs)
576
-
577
- // Insert after the wasmManifest line (after line that sets wasmManifest)
578
- manifestLine := "let wasmManifest = JSON.parse(wasmManifestString);"
579
- result = strings.Replace(result, manifestLine, manifestLine+"\n"+bootstrapServersLine, 1)
580
-
517
// Set headers for no caching
518
w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
519
w.Header().Set("Pragma", "no-cache")
@@ -586,10 +522,7 @@ func serveDynamicServiceWorker(w http.ResponseWriter, r *http.Request) {
522
523
// Send response
524
w.WriteHeader(http.StatusOK)
589
- w.Write([]byte(result))
525
+ w.Write(content)
526
591
- log.Debug().
592
- Str("portalUIURL", portalUIURL).
593
- Str("wasmHash", wasmHash).
594
- Msg("Served dynamic service-worker.js")
527
+ log.Debug().Msg("Served service-worker.js")
528
}
cmd/webclient/service-worker.js
+55
-19
@@ -1,7 +1,7 @@
1
//const wasm_exec_URL = "https://cdn.jsdelivr.net/gh/golang/go@go1.25.3/lib/wasm/wasm_exec.js";
2
-let BASE_PATH = "<PORTAL_UI_URL>";
3
-let wasmManifestString = '"<WASM_MANIFEST>"';
4
-let wasmManifest;
2
+const BASE_PATH = self.location.origin || "";
3
+let wasmManifest = null;
4
+let wasmManifestPromise = null;
5
6
// Debug mode detection (disable verbose logging in production)
7
const DEBUG_MODE = self.location.hostname === 'localhost' ||
@@ -14,19 +14,52 @@ function debugLog(...args) {
14
}
15
}
16
17
-// Parse manifest with error handling
18
-try {
19
- wasmManifest = JSON.parse(wasmManifestString);
20
- debugLog("[SW] Manifest parsed successfully:", wasmManifest);
21
-} catch (error) {
22
- console.error("[SW] Failed to parse WASM manifest:", error);
23
- console.error("[SW] Manifest string:", wasmManifestString);
24
- // Use fallback manifest
25
- wasmManifest = {
26
- wasmFile: "main.wasm",
27
- wasmUrl: null
28
- };
29
- console.warn("[SW] Using fallback manifest:", wasmManifest);
17
+// Load manifest from backend (decouples SW from Go template)
18
+async function loadManifest() {
19
+ if (wasmManifest) {
20
+ return wasmManifest;
21
+ }
22
+
23
+ if (wasmManifestPromise) {
24
+ return wasmManifestPromise;
25
+ }
26
+
27
+ wasmManifestPromise = (async () => {
28
+ try {
29
+ debugLog("[SW] Fetching WASM manifest...");
30
+ const response = await fetch("/frontend/manifest.json", { cache: "no-cache" });
31
+
32
+ if (!response.ok) {
33
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
34
+ }
35
+
36
+ const manifest = await response.json();
37
+ wasmManifest = manifest;
38
+
39
+ // Expose bootstrap servers to WASM runtime (service worker global)
40
+ if (manifest.bootstraps) {
41
+ self.__BOOTSTRAP_SERVERS__ = manifest.bootstraps;
42
+ debugLog("[SW] Bootstraps loaded from manifest:", manifest.bootstraps);
43
+ }
44
+
45
+ debugLog("[SW] Manifest loaded successfully:", manifest);
46
+ return manifest;
47
+ } catch (error) {
48
+ console.error("[SW] Failed to load WASM manifest:", error);
49
+
50
+ // Fallback manifest
51
+ wasmManifest = {
52
+ wasmFile: "main.wasm",
53
+ wasmUrl: null
54
+ };
55
+ console.warn("[SW] Using fallback manifest:", wasmManifest);
56
+ return wasmManifest;
57
+ } finally {
58
+ wasmManifestPromise = null;
59
+ }
60
+ })();
61
+
62
+ return wasmManifestPromise;
63
}
64
65
let wasm_exec_URL = BASE_PATH + "/frontend/wasm_exec.js";
@@ -388,12 +421,15 @@ async function runWASM() {
421
}
422
423
try {
424
+ // Ensure manifest is loaded
425
+ const manifest = await loadManifest();
426
+
427
// Determine WASM URL from manifest
428
let wasm_URL;
393
- if (wasmManifest.wasmUrl && new URL(wasmManifest.wasmUrl).protocol !== "http:") {
394
- wasm_URL = wasmManifest.wasmUrl;
429
+ if (manifest.wasmUrl && new URL(manifest.wasmUrl).protocol !== "http:") {
430
+ wasm_URL = manifest.wasmUrl;
431
} else {
396
- wasm_URL = `/frontend/${wasmManifest.wasmFile}`;
432
+ wasm_URL = `/frontend/${manifest.wasmFile}`;
433
}
434
debugLog("[SW] WASM URL:", wasm_URL);
435