Making WASM a First-Class Language on the Web
Component Model: Calling Web APIs Directly Without JS Glue
Explores the current problem of WebAssembly being treated as a second-class citizen on the web, and how Mozilla's Component Model aims to solve it.
Architecture Diagram
component {
import std:web/console;
}
use std_web::console;
console::log("hello, world");
How It Works
Current: WASM requires manual loading via JS APIs like WebAssembly.instantiateStreaming()
Current: No direct access to DOM, console, or Web APIs โ JS glue code serves as bridge
Current: Each language needs separate binding tools, rustc --target=wasm output doesn't run directly in browsers
Component Model: Declare needed Web APIs with WIT (Interface Description Language)
Component Model: Browser loads directly via <script type="module" src="component.wasm">
Component Model: Hybrid usage from JS via import { fn } from "lib.wasm"
Result: Complete JS glue code elimination โ 45% performance overhead resolved, unified toolchain
Pros
- ✓ Complete JS glue code elimination โ 45% DOM performance overhead resolved
- ✓ Load WASM directly via <script> tag just like JS
- ✓ Unified toolchain per language โ run directly in browser from standard compiler
- ✓ Type-safe Web API interface declarations with WIT
- ✓ Hybrid usage with JS possible โ gradual adoption
- ✓ Runs outside browser too (Wasmtime) โ reuse web and server code
Cons
- ✗ Still under standardization โ too early for production use
- ✗ Frequent spec changes cause tooling churn
- ✗ Difficult polyfill/feature detection โ may lose JS bridge flexibility
- ✗ Component Model itself introduces new complexity (WIT learning curve)
- ✗ JS shim cost already negligible for WebGL2/WebGPU
- ✗ Memory management unresolved โ unclear if Wasm GC proposal is needed for DOM references