The Ecosystem: Languages, Tools, and Real Uses
This chapter surveys other source languages (C/C++, Go, AssemblyScript, Zig), key tooling (wabt, wasm-opt), and how major products actually use Wasm.
Languages That Target Wasm
Rust is the most Wasm-idiomatic language, but far from the only one.
C and C++ via Emscripten
Emscripten is a full LLVM-based toolchain that compiles C and C++ to Wasm (or to asm.js, historically). It's been around since before Wasm itself and is how most large legacy codebases get to the browser.
emcc main.c -o out.html -s WASM=1
Emscripten generates JS glue, HTML shells, and the .wasm. It simulates a POSIX-ish environment (stdio, filesystem, even threads) via JS.
Real use: Adobe Photoshop on the web (C++ via Emscripten), Google Earth, AutoCAD Web.
Go via TinyGo
The standard Go compiler can target Wasm (GOOS=js GOARCH=wasm), but the output is large (2+ MB for a hello world) because it embeds the whole Go runtime including its garbage collector.
TinyGo is a smaller alternative, optimized for embedded and Wasm targets:
tinygo build -o out.wasm -target wasm main.go
TinyGo's output is kilobytes, not megabytes. Supports a subset of the Go standard library; most common packages work, some don't.
AssemblyScript
A TypeScript-like language that compiles directly to Wasm. Aimed at web developers who want Wasm performance without learning Rust or C.
export function add(a: i32, b: i32): i32 {
return a + b;
}
asc assembly/index.ts --target release
AssemblyScript is less popular than Rust for new projects, but still ships in production: Shopify tried it, some ML inference libraries use it, and its syntax is a gentle on-ramp.
Zig
Zig's Wasm output is tiny. The language's "no hidden allocation" philosophy fits Wasm's constrained environment well.
export fn add(a: i32, b: i32) i32 {
return a + b;
}
zig build-lib main.zig -target wasm32-freestanding -dynamic -rdynamic
Zig is a good choice if you want near-Rust-level control with less syntactic ceremony and no macro layer.
.NET via Blazor WebAssembly
.NET runs on Wasm via Mono compiled to Wasm, with ahead-of-time compilation options. Blazor WebAssembly lets you build a frontend app in C# that runs entirely in the browser.
Binary sizes are large (10+ MB typical). Ahead-of-time and trimming bring it down. Nice fit if your team is .NET-first.
Others
Java (TeaVM, CheerpJ), Python (Pyodide), Ruby (ruby.wasm), Kotlin (Kotlin/Wasm), Swift (experimental), Haskell (Asterius): they all exist. Bundle size and feature completeness vary.
Picking a Source Language
- New project, performance-critical: Rust.
- Existing C/C++ codebase: Emscripten.
- Existing Go service: TinyGo.
- Tiny output, minimal deps: Zig or AssemblyScript.
- Already a .NET shop: Blazor.
The source language choice doesn't affect where the Wasm runs; it affects developer experience, bundle size, and ecosystem.
Essential Tooling
Four tools that pay for themselves the first week.
wabt (WebAssembly Binary Toolkit)
A suite of utilities for working with Wasm files.
wasm2wat foo.wasm # disassemble to text
wat2wasm foo.wat # assemble from text
wasm-objdump -d foo.wasm # disassembler-style view
wasm-validate foo.wasm # validate
wasm-strip foo.wasm # remove custom sections (names, debug info)
Install:
brew install wabt
wasm-opt (from binaryen)
The optimizer. Shrinks and speeds up Wasm modules.
wasm-opt -Oz in.wasm -o out.wasm # optimize for size
wasm-opt -O3 in.wasm -o out.wasm # optimize for speed
wasm-opt -O4 in.wasm -o out.wasm # aggressive speed
Always run wasm-opt on release builds. It typically shaves 10 to 30% of size and can double speed on unoptimized code.
twiggy
Profiler for Wasm binary size. "Where are the bytes going?"
twiggy top out.wasm
twiggy top out.wasm -n 20
twiggy dominators out.wasm
Tells you which functions are largest. Great for targeted trimming.
wasm-tools
The Swiss Army knife for Wasm and the Component Model.
wasm-tools print foo.wasm # to WAT
wasm-tools validate foo.wasm
wasm-tools component new # wrap a core module as a component
wasm-tools compose ... # link components together
Use when working with the Component Model (Chapter 10).
Real-World Uses
Where Wasm actually ships, as of early 2026.
Figma
Figma's rendering engine is C++ compiled to Wasm. It's the reason Figma renders complex designs at 60fps in a browser tab. When Figma launched, Wasm was brand new; the bet paid off.
Photoshop on the Web
Adobe ported the C++ Photoshop codebase to the browser via Emscripten. Millions of lines of C++ run in Wasm. Bandwidth and cold start are still challenges, but the feature coverage is extensive.
Shopify Functions
Merchants write Rust, compile to Wasm, upload to Shopify. Shopify runs the Wasm in a sandboxed runtime for every checkout, applying custom discount logic, shipping rates, and delivery customizations at scale.
Cloudflare Workers and Fastly Compute@Edge
Edge compute platforms where Wasm is a first-class runtime alongside V8 isolates. Cold-start times of a few milliseconds make Wasm attractive for per-request code.
Envoy and Istio Wasm Filters
Envoy (the proxy) supports Wasm filters. You write a filter in Rust, compile to Wasm, load into Envoy at runtime without recompiling. Istio's extension mechanism uses this.
Postgres Extensions
Some teams run Postgres extensions in Wasm instead of native .so files, for safer distribution and tenant isolation in managed-Postgres offerings.
Browser ML Inference
ONNX Runtime Web, TensorFlow.js, and ML libraries use Wasm SIMD for fast inference in the browser. Running small-to-medium models client-side keeps latency low and data private.
Plugin Systems (Dapr, SingleStore, Suborbital)
"Run user-supplied code in a sandbox" is a common server-side need. Dapr, SingleStore, and others use Wasm as their plugin runtime.
Patterns Across Uses
Across all these examples:
- Wasm isn't the whole application; it's a CPU-bound core inside a JS or native host.
- The boundary is carefully designed: minimal crossings, typed interfaces.
- Sandboxing (for untrusted code) or portability (for existing C++) is the main motivation.
- Performance matters but so does distribution: "one binary, many targets" is often the pitch.
Community
Wasm moves fast. Useful communities and news:
- Bytecode Alliance (bytecodealliance.org): stewards of Wasmtime, Cranelift, WASI.
- WebAssembly Weekly newsletter (webassemblyweekly.com): weekly roundup.
- r/WebAssembly and Hacker News Wasm threads.
- CNCF TAG Runtime: where CNCF projects intersect with Wasm (WasmEdge, Spin, others).
Common Pitfalls
Picking the wrong source language. The costs (bundle size, feature availability, debugging) are bigger than you think. Try the hello-world in each candidate before committing.
Skipping wasm-opt. Leaves a lot of bytes and cycles on the table.
Not profiling with twiggy. Your Wasm is bigger than it needs to be; you just don't know which function.
Following the hype cycle. Wasm is not a replacement for JS, for containers, or for processes. It's a particular tool for particular jobs. Use it where it fits.
Next Steps
Continue to 12-best-practices.md for the habits that keep Wasm modules healthy.