EdgeSync ships two WebAssembly builds. Both are produced by the leaf module — same agent API (New -> Start -> Stop) — but with different runtimes, networking models, and SQLite drivers.
| Target | GOOS | GOARCH | SQLite driver | Build entry | Output |
|---|---|---|---|---|---|
| WASI | wasip1 |
wasm |
ncruces (WASM-based) |
leaf/cmd/leaf |
bin/leaf.wasm |
| Browser | js |
wasm |
ncruces + OPFS VFS |
leaf/cmd/wasm |
bin/leaf-browser.wasm + bin/wasm_exec.js |
Building
Both targets are driven from the repo root:
make wasm-wasi # produces bin/leaf.wasm
make wasm-browser # produces bin/leaf-browser.wasm and copies wasm_exec.js
make wasm # both
The Makefile cds into leaf/ because the leaf agent lives in its own Go module. The browser recipe copies wasm_exec.js from $(go env GOROOT)/lib/wasm/ (Go 1.26+ path); older Go releases used misc/wasm/.
SQLite driver selection
leaf/cmd/leaf/main.go uses build-tagged blank imports to pick the right driver:
driver_default.go(!wasip1) —modernc(pure Go, the standard driver)driver_wasi.go(wasip1) —ncruces(WASM-based;modernc.org/libchas nowasip1port)
The browser entry (leaf/cmd/wasm/main.go) is //go:build js and imports ncruces directly.
Runtimes
- WASI runs under any wasip1 host:
wasmtime,wasmer,wazero, browserWebAssembly.Moduleinstantiated with WASI shims. Full HTTP serving works (host networking). - Browser runs in a Web Worker via
wasm_exec.js. NATS connects vianats.SetCustomDialer()over a WebSocket. Exposes JS globals:edgesync.newAgent,.start,.stop,.syncNow. Seeleaf/cmd/wasm/worker.js.
Known limitations
- Browser cannot listen.
serve_http_js.goandsignals_js.goare build-tagged no-ops — there is no HTTP server in browser builds. stash/andundo/are excluded (//go:build !js) — checkout features, not needed for sync.- Telemetry is a no-op on both wasm targets (
leaf/telemetry/noop.gocoverswasip1 || js). OTel exporters require host networking that browser builds cannot reach. - Binaries are large.
leaf.wasmandleaf-browser.wasmare each ~50 MB unstripped — the SQLite driver dominates. Compression (gzip/brotli) on the serving layer is recommended.
See agent-deployment.md (WASM Targets section) for the agent lifecycle in WASM and testing-strategy.md for how WASM builds are exercised in CI.