On the web
The same application runs in a browser. The window becomes a canvas, the CPU renderer draws into it, and damage tracking works exactly as on the desktop.
What changes on the web
- The window is a
<canvas>appended to the page's body. It starts atWindowOptions::sizeand follows any size the page gives it, so a page that sizes the canvas to the viewport gets an application that resizes with the browser window and with page zoom. - The CPU renderer draws every frame. The
gpufeature is a desktop feature. runreturnsOk(())as soon as the browser's event loop has started, before the first frame. Errors detected before that, such as a translucent clear color, still come back as anErr.- The bundled fonts are the only fonts.
system-fontsis not available. - The window commands
start_move,start_resize,toggle_maximizeandclosedo nothing, because the page owns the canvas, andmaximizedstaysfalse.WindowOptions::decorationsandapp_idhave no effect either, andmin_sizebecomes the canvas's minimum size. - There is no system clipboard, so copy and paste work only inside the application, and no screen reader support yet. See Known limits.
Build
Add the target once, and install the wasm-bindgen command line tool:
rustup target add wasm32-unknown-unknown
cargo install wasm-bindgen-cli --version <the version in your Cargo.lock>The tool's version must match the wasm-bindgen crate in your Cargo.lock. cargo tree -i wasm-bindgen --target wasm32-unknown-unknown shows which one that is.
Build the application and generate the JavaScript glue:
cargo build --release --target wasm32-unknown-unknown
wasm-bindgen --target web --out-dir web/pkg \
target/wasm32-unknown-unknown/release/my-app.wasmThe page
web/index.html loads the generated module, which runs your main. This one sizes the canvas to the whole viewport:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>My app</title>
<style>
html, body { margin: 0; height: 100%; background: #101115; }
canvas { display: block; width: 100vw !important; height: 100vh !important; }
canvas:focus { outline: none; }
</style>
</head>
<body>
<script type="module">
import init from "./pkg/my-app.js";
init();
</script>
</body>
</html>The !important matters: the window sets an inline size on its canvas, and the page's rule overrides it.
Serve the web directory with any static file server and open it. Browsers do not load ES modules from file: URLs, so opening the file directly does not work.
Try the example
The repository has a complete web example, a grid of boxes where one box changes per frame and a caption reports what each present copied:
cargo build --release --target wasm32-unknown-unknown --example web_boxes -p smudge-platform
wasm-bindgen --target web --out-dir crates/smudge-platform/examples/web/pkg \
target/wasm32-unknown-unknown/release/examples/web_boxes.wasm
cd crates/smudge-platform/examples/web
python3 -m http.server 8000Size
A release build of the example is about 5.6 MB of wasm, 1.8 MB gzipped, embedded fonts included. The complex-scripts feature adds about 2.2 MB gzipped, so leave it off for the web unless the application shows Thai, Lao, Khmer or Burmese.