spinny:~/writing $ less webassembly-wasm-complete-guide.md
12WebAssembly (WASM) begann als Moglichkeit, C++ im Browser auszufuhren. Im Jahr 2026 lauft es uberall - Browser, Server, Edge-Netzwerke, eingebettete Gerate - und betreibt einige der anspruchsvollsten Anwendungen im Web. Figmas Rendering-Engine, Adobe Photoshop im Web, die Videoverarbeitung von Google Meet und Cloudflares Edge-Compute-Plattform laufen alle auf WebAssembly.34Chrome Platform Status beziffert WASM auf etwa 5,5 % aller Chrome-Seitenaufrufe Anfang 2026, gegenuber 4,5 % im Vorjahr. Mit WASM 3.0 als W3C-Standard und WASI auf dem Weg zur Version 1.0 hat das Okosystem einen Wendepunkt erreicht.56Dieser Leitfaden behandelt alles, was du wissen musst, um mit WebAssembly zu entwickeln.78## Was ist WebAssembly?910WebAssembly ist ein binares Befehlsformat, das als Kompilierungsziel konzipiert wurde. Du schreibst Code in einer Hochsprache (Rust, C, C++, Go, Kotlin), kompilierst ihn zu `.wasm` und fuhrst ihn in jeder Umgebung aus, die eine WASM-Laufzeitumgebung hat - Browser, Node.js, Cloudflare Workers, Wasmtime oder Wasmer.1112```mermaid13graph LR14 Rust[Rust / C / C++] --> Compiler[Compiler]15 Compiler --> WASM[.wasm Binary]16 WASM --> Browser[Browser V8/SpiderMonkey]17 WASM --> Server[Server Wasmtime]18 WASM --> Edge[Edge Cloudflare Workers]19 WASM --> Embedded[Embedded WAMR]20```2122### Wie es funktioniert2324WASM ist eine **stapelbasierte virtuelle Maschine**. Funktionen legen Werte auf einem Operandenstapel ab und nehmen sie wieder herunter. Die Host-Laufzeitumgebung (V8 in Chrome, SpiderMonkey in Firefox) kompiliert den WASM-Bytecode per JIT zu nativem Maschinencode, weshalb die Leistung nahezu nativ ist.2526Wichtige Eigenschaften:2728- **Isolierte Ausfuhrung**: WASM-Module konnen nur auf Ressourcen zugreifen, die der Host explizit gewahrt. Kein Dateisystem, kein Netzwerk, kein Betriebssystemzugriff, es sei denn, er wird erlaubt. Das ist grundlegend anders als nativer Code.29- **Linearer Speicher**: ein einzelner zusammenhangender `ArrayBuffer`, der zwischen WASM und dem Host geteilt wird. Komplexe Daten (Strings, Structs) werden durch Schreiben in den Speicher und Teilen eines Pointers ubergeben.30- **Typbeschrankt**: WASM unterstutzt nativ nur vier Typen: `i32`, `i64`, `f32`, `f64`. Alles andere (Strings, Arrays, Objekte) erfordert Kodierung uber linearen Speicher oder das Component Model.31- **Portabel**: dieselbe `.wasm`-Binardatei lauft auf jeder Plattform mit einer WASM-Laufzeitumgebung, ohne Neukompilierung.3233### WASM vs JavaScript3435WASM ersetzt JavaScript nicht. Es erganzt es.3637| Aspekt | JavaScript | WebAssembly |38|--------|-----------|-------------|39| **Parsing** | Parsen + Kompilieren zur Laufzeit | Vorkompilierte Binardatei, nur Dekodierung |40| **Ausfuhrungsgeschwindigkeit** | JIT-optimiert, variabel | Nahezu nativ, konsistent |41| **Startzeit** | Schnell fur kleine Skripte | Schnelle Dekodierung, vorhersagbar |42| **DOM-Zugriff** | Direkt | Indirekt (uber JS-Glue-Code) |43| **Am besten fur** | UI, DOM-Manipulation, Event-Handling | CPU-intensive Berechnungen |44| **Garbage Collection** | Eingebaut | WasmGC (neu) oder manuell |4546Verwende JavaScript fur UI- und DOM-Arbeit. Verwende WASM fur rechenintensive Aufgaben: Bildverarbeitung, Videokodierung, Physiksimulationen, Kryptografie, Datenverarbeitung.4748## WASM 3.0: Was ist neu4950WebAssembly 3.0 wurde im September 2025 zum W3C-Standard und standardisierte neun Features, die seit Jahren in Entwicklung waren.5152| Feature | Was es ermoglicht |53|---------|----------------|54| **WasmGC** | Native Garbage Collection in WASM. Verwaltete Sprachen (Java, Kotlin, Dart) konnen zu WASM kompilieren, ohne ihre eigene GC-Laufzeitumgebung mitzuliefern. Unterstutzt in Chrome 119+, Firefox 120+, Safari 18.2+. |55| **Exception Handling** | Natives `try`/`catch` in WASM. Zuvor erforderten Exceptions teure Roundtrips zu JavaScript. |56| **Tail Calls** | Ermoglicht effiziente Rekursion ohne Stack Overflow. Entscheidend fur funktionale Sprachen. |57| **Relaxed SIMD** | 128-Bit-Vektorbefehle fur parallele Datenverarbeitung. Ermoglicht hardwarespezifische Optimierungen. |58| **Memory64** | Durchbricht die 4-GB-Grenze des linearen Speichers. Erforderlich fur grossangelegte Datenverarbeitung. |59| **Multi-memory** | Mehrere unabhangige Speicherbereiche in einem Modul. |6061Am wirkungsvollsten ist **WasmGC**. Zuvor bedeutete das Kompilieren von Java oder Kotlin zu WASM, einen kompletten Garbage Collector als Teil der Binardatei mitzuliefern, was die Dateigrossen aufblahte. Jetzt ubernimmt die GC des Browsers die Speicherverwaltung fur WASM-Module, genau wie fur JavaScript.6263## WASI: WebAssembly jenseits des Browsers6465WASM im Browser ist leistungsstark, aber **WASI (WebAssembly System Interface)** macht WASM zu einer universellen Laufzeitumgebung. WASI bietet standardisierte Schnittstellen fur Systemressourcen - Dateien, Netzwerk, Uhren, Zufallszahlen - und ermoglicht es WASM-Modulen, ausserhalb des Browsers zu laufen.6667```mermaid68graph TD69 subgraph "Browser"70 B[WASM Module] --> Web[Web APIs\nDOM, Fetch, Canvas]71 end7273 subgraph "Server / Edge / Embedded"74 S[WASM Module] --> WASI[WASI Interfaces]75 WASI --> FS[wasi:filesystem]76 WASI --> Net[wasi:sockets]77 WASI --> HTTP[wasi:http]78 WASI --> Clock[wasi:clocks]79 WASI --> Rand[wasi:random]80 end81```8283WASI Preview 2 (das aktuelle stabile Release) definiert diese Schnittstellen:8485- `wasi:filesystem` - Dateioperationen uber Capability-Handles (nicht traditionelle Dateideskriptoren)86- `wasi:sockets` - TCP/UDP-Netzwerk87- `wasi:http` - HTTP-Request/Response-Verarbeitung88- `wasi:clocks` - Wanduhr, monotone Uhr89- `wasi:random` - kryptografischer Zufall90- `wasi:cli` - Kommandozeilenargumente, Umgebungsvariablen, Stdio9192Das Schlusselprinzip ist **Capability-basierte Sicherheit**: Ein WASM-Modul kann nicht auf das Dateisystem zugreifen, es sei denn, der Host gewahrt explizit ein Handle fur ein bestimmtes Verzeichnis. Das macht WASI grundlegend sicherer als das Ausfuhren nativer Binardateien.9394### Der Weg zu WASI 1.09596WASI 0.3.0 (mit Async/Concurrency-Primitiven) wird fur 2026 erwartet, gefolgt von WASI 1.0. Die wichtigste Neuerung ist sprachintegriertes Async mit Zero-Copy-Streaming-I/O.9798## Das Component Model99100Kern-WASM-Module konnen nur Zahlen austauschen. Das **Component Model** lost diese Einschrankung, indem es ein reichhaltiges Typsystem und eine Kompositionsschicht uber WASM legt.101102### WIT (WebAssembly Interface Types)103104WIT ist eine Interface Definition Language, mit der Komponenten ihre Imports und Exports mit reichhaltigen Typen deklarieren konnen - Strings, Records, Listen, Varianten, Enums - nicht nur `i32` und `f64`.105106```wit107// calculator.wit108package myorg:calculator@1.0.0;109110interface operations {111 record calculation {112 expression: string,113 result: f64,114 timestamp: u64,115 }116117 add: func(a: f64, b: f64) -> f64;118 multiply: func(a: f64, b: f64) -> f64;119 history: func() -> list<calculation>;120}121122world calculator {123 export operations;124}125```126127Toolchains wie `wit-bindgen` generieren sprachspezifische Bindings aus WIT-Dateien. Eine Rust-Komponente und eine Python-Komponente konnen Strings, Records und Listen uber WIT-Vertrage austauschen, ohne dass eine Seite die Implementierungssprache der anderen kennen muss.128129## Dein erstes WASM-Modul mit Rust bauen130131Rust hat das ausgereifteste WASM-Tooling. Lass uns ein praktisches Beispiel bauen: ein Bildverarbeitungsmodul, das im Browser lauft.132133### Setup134135```bash136# Install the WASM target for Rust137rustup target add wasm32-unknown-unknown138139# Install wasm-pack (builds Rust to WASM + generates JS bindings)140cargo install wasm-pack141142# Create a new library project143cargo new --lib image-processor144cd image-processor145```146147### Cargo.toml konfigurieren148149```toml150[package]151name = "image-processor"152version = "0.1.0"153edition = "2021"154155[lib]156crate-type = ["cdylib"]157158[dependencies]159wasm-bindgen = "0.2"160```161162### Den Rust-Code schreiben163164```rust165// src/lib.rs166use wasm_bindgen::prelude::*;167168/// Convert an image buffer to grayscale.169/// Input: RGBA pixel data as a flat u8 array (4 bytes per pixel).170/// Output: Modified in place for zero-copy performance.171#[wasm_bindgen]172pub fn grayscale(pixels: &mut [u8]) {173 for chunk in pixels.chunks_exact_mut(4) {174 let r = chunk[0] as f32;175 let g = chunk[1] as f32;176 let b = chunk[2] as f32;177 // ITU-R BT.709 luminance coefficients178 let gray = (0.2126 * r + 0.7152 * g + 0.0722 * b) as u8;179 chunk[0] = gray;180 chunk[1] = gray;181 chunk[2] = gray;182 // chunk[3] is alpha, leave unchanged183 }184}185186/// Adjust brightness of an image.187/// factor > 1.0 brightens, < 1.0 darkens.188#[wasm_bindgen]189pub fn adjust_brightness(pixels: &mut [u8], factor: f32) {190 for chunk in pixels.chunks_exact_mut(4) {191 chunk[0] = ((chunk[0] as f32 * factor).min(255.0)) as u8;192 chunk[1] = ((chunk[1] as f32 * factor).min(255.0)) as u8;193 chunk[2] = ((chunk[2] as f32 * factor).min(255.0)) as u8;194 }195}196197/// Invert all colors in the image.198#[wasm_bindgen]199pub fn invert(pixels: &mut [u8]) {200 for chunk in pixels.chunks_exact_mut(4) {201 chunk[0] = 255 - chunk[0];202 chunk[1] = 255 - chunk[1];203 chunk[2] = 255 - chunk[2];204 }205}206207/// Calculate the average brightness of an image (0-255).208#[wasm_bindgen]209pub fn average_brightness(pixels: &[u8]) -> f32 {210 let mut total: f64 = 0.0;211 let pixel_count = pixels.len() / 4;212 for chunk in pixels.chunks_exact(4) {213 let luminance = 0.2126 * chunk[0] as f64214 + 0.7152 * chunk[1] as f64215 + 0.0722 * chunk[2] as f64;216 total += luminance;217 }218 (total / pixel_count as f64) as f32219}220```221222### Build223224```bash225wasm-pack build --target web226```227228Dies erzeugt ein `pkg/`-Verzeichnis mit:229- `image_processor_bg.wasm` - die kompilierte WASM-Binardatei230- `image_processor.js` - JavaScript-Glue-Code mit TypeScript-Definitionen231- `package.json` - bereit zur Veroffentlichung auf npm232233### Verwendung in JavaScript234235```html236<!DOCTYPE html>237<html>238<head><title>WASM Image Processor</title></head>239<body>240 <canvas id="canvas" width="800" height="600"></canvas>241 <button onclick="applyGrayscale()">Grayscale</button>242 <button onclick="applyBrightness()">Brighten</button>243 <button onclick="applyInvert()">Invert</button>244245 <script type="module">246 import init, { grayscale, adjust_brightness, invert } from "./pkg/image_processor.js";247248 let ctx;249 let imageData;250251 async function setup() {252 await init();253 const canvas = document.getElementById("canvas");254 ctx = canvas.getContext("2d");255256 // Load an image onto the canvas257 const img = new Image();258 img.onload = () => {259 ctx.drawImage(img, 0, 0);260 imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);261 };262 img.src = "photo.jpg";263 }264265 window.applyGrayscale = () => {266 grayscale(imageData.data);267 ctx.putImageData(imageData, 0, 0);268 };269270 window.applyBrightness = () => {271 adjust_brightness(imageData.data, 1.3);272 ctx.putImageData(imageData, 0, 0);273 };274275 window.applyInvert = () => {276 invert(imageData.data);277 ctx.putImageData(imageData, 0, 0);278 };279280 setup();281 </script>282</body>283</html>284```285286Die zentrale Erkenntnis: `imageData.data` ist ein `Uint8ClampedArray`, das von einem `ArrayBuffer` unterstutzt wird. Wenn es an WASM ubergeben wird, teilt es denselben Speicher - kein Kopieren. Die Rust-Funktion andert Pixel direkt, und die JavaScript-Seite sieht die Anderungen sofort.287288## Low-Level: Manuelle WASM-Instanziierung289290Wenn du `wasm-bindgen` nicht verwenden mochtest, kannst du WASM-Module direkt instanziieren:291292```javascript293const response = await fetch("calculator.wasm");294const { instance } = await WebAssembly.instantiateStreaming(response, {295 env: {296 // Functions the WASM module can call297 log_result: (value) => console.log("Result:", value),298 },299});300301// Call exported functions302const { add, multiply } = instance.exports;303console.log(add(5, 3)); // 8304console.log(multiply(4, 7)); // 28305```306307Das ist nutzlich, wenn du minimalen Overhead willst und kein reichhaltiges Typ-Interop brauchst.308309## Leistung: WASM vs JavaScript310311Reale Benchmarks zeigen signifikante Beschleunigungen fur CPU-intensive Aufgaben:312313| Aufgabe | JavaScript | WASM | Beschleunigung |314|---------|-----------|------|---------|315| 4K-Bildverarbeitung | 180ms | 8ms (mit SIMD) | 22x |316| Bildskalierung (4K) | 250ms | 45ms | 5,5x |317| Physiksimulation (10K Objekte) | Frame-Einbruche | Flussige 60fps | ~10x |318| JSON-Parsing (grosser Payload) | 12ms | 3ms | 4x |319| Kryptografisches Hashing | 45ms | 6ms | 7,5x |320321WASM lauft mit etwa 95 % der nativen Code-Geschwindigkeit. Die grossten Gewinne kommen von:322- Vorhersagbare Leistung (kein JIT-Aufwarmen, keine GC-Pausen)323- SIMD-Befehle fur parallele Datenverarbeitung324- Direkter Speicherzugriff ohne Garbage-Collector-Interferenz325326Wo WASM NICHT schneller ist: DOM-Manipulation, kleine Berechnungen, I/O-gebundene Aufgaben. JavaScript ist bereits dafur optimiert.327328## Produktions-Anwendungsfalle329330### Figma: Echtzeit-Vektor-Rendering331332Figmas Kern-Rendering-Engine ist in C++ geschrieben und zu WASM kompiliert. Jede Form, jeder Verlauf und jeder Effekt wird in WASM berechnet und auf ein Canvas-Element gezeichnet. So kann Figma komplexe Designs mit Tausenden von Ebenen bei 60fps im Browser verarbeiten - eine Leistung, die in reinem JavaScript unmoglich ware.333334### Adobe Photoshop im Web335336Adobe hat wichtige Photoshop-Filter und -Werkzeuge mit Rust nach WASM portiert. Ihre Benchmarks zeigen 4K-Bildverarbeitung in 22ms mit WASM SIMD gegenuber 180ms in JavaScript - eine 8-fache Verbesserung, die Echtzeit-Filtervorschauen ermoglicht.337338### Cloudflare Workers339340Cloudflare fuhrt WASM-Module in V8-Isolates an uber 330 Edge-Standorten aus. Kaltstarts liegen bei 1-5ms (im Vergleich zu 100-500ms bei containerbasierten Serverless-Losungen). Im Februar 2026 haben sie Llama-3-8b-Inferenz uber ihr Edge-Netzwerk mit WASM bereitgestellt.341342### Google Meet343344Hintergrundunschaerfe und virtuelle Hintergrunde in Google Meet nutzen WASM mit SIMD fur Echtzeit-Videoverarbeitung. Das WASM-Modul verarbeitet jeden Videoframe schnell genug, um flussiges Video bei 30fps aufrechtzuerhalten.345346## Browser-Unterstutzung (2026)347348| Feature | Chrome | Firefox | Safari | Edge |349|---------|--------|---------|--------|------|350| Core WASM | Vollstandig | Vollstandig | Vollstandig | Vollstandig |351| Threads | Ja | Ja | Ja | Ja |352| SIMD (128-Bit) | Ja | Ja | Ja | Ja |353| WasmGC | 119+ | 120+ | 18.2+ | Ja |354| Exception Handling | Ja | Ja | Ja | Ja |355| Memory64 | Ja | Ja | Teilweise | Ja |356357Alle grossen Browser unterstutzen WASM vollstandig. Die neueren Features (WasmGC, Exception Handling) sind breit verfugbar.358359## Tooling-Referenz360361| Tool | Zweck | Installation |362|------|---------|---------|363| **wasm-pack** | Rust zu WASM bauen, npm-Pakete generieren | `cargo install wasm-pack` |364| **wasm-bindgen** | Rust/JS-Interop-Bindings (von wasm-pack genutzt) | Dependency in Cargo.toml |365| **wasm-opt** | Optimierung der Binardateigrosse (50%+ Reduktion) | Teil von Binaryen: `brew install binaryen` |366| **wit-bindgen** | Bindings aus WIT-Dateien generieren | `cargo install wit-bindgen-cli` |367| **Wasmtime** | Serverseitige WASM-Laufzeitumgebung (Referenz-WASI-Implementierung) | `brew install wasmtime` |368| **Wasmer** | Alternative WASM-Laufzeitumgebung mit WASI-Unterstutzung | `curl https://get.wasmer.io -sSfL \| sh` |369| **wasm-feature-detect** | Laufzeit-Browser-Feature-Erkennung | `npm install wasm-feature-detect` |370371### Binardateigrosse optimieren372373WASM-Binardateien konnen gross sein. So verkleinerst du sie:374375```toml376# Cargo.toml377[profile.release]378opt-level = "z" # Optimize for size379lto = true # Link-time optimization380codegen-units = 1 # Better optimization, slower compile381strip = true # Strip debug symbols382```383384```bash385# Build in release mode386wasm-pack build --release --target web387388# Further optimize with wasm-opt389wasm-opt -Oz pkg/image_processor_bg.wasm -o pkg/image_processor_bg.wasm390```391392Ein typisches Rust-WASM-Modul schrumpft mit diesen Optimierungen von 500KB auf unter 50KB.393394## Einstiegs-Roadmap395396```mermaid397flowchart TD398 A[Week 1: Basics] --> B[Week 2: Real Project]399 B --> C[Week 3: WASI and Server-side]400 C --> D[Month 2+: Production]401402 A --> A1[Install Rust + wasm-pack]403 A --> A2[Build hello-world WASM module]404 A --> A3[Call WASM functions from JavaScript]405406 B --> B1[Build image processor or game physics]407 B --> B2[Use wasm-bindgen for rich types]408 B --> B3[Benchmark against pure JS]409410 C --> C1[Run WASM with Wasmtime]411 C --> C2[Explore WASI interfaces]412 C --> C3[Try Component Model with WIT]413414 D --> D1[Optimize binary size]415 D --> D2[Use SIMD for parallelism]416 D --> D3[Deploy to Cloudflare Workers or browser]417```418419## Fazit420421WebAssembly ist nicht mehr experimentell. Es ist eine Produktionstechnologie, die von einigen der anspruchsvollsten Anwendungen im Web genutzt wird. Nahezu native Leistung, sandboxed Sicherheit und universelle Portabilitat - kein anderes Kompilierungsziel bietet dir alle drei.422423Du musst nicht deine gesamte Anwendung in WASM umschreiben. Beginne mit einer einzelnen CPU-intensiven Funktion - einem Bildfilter, einem Daten-Parser, einer Physikberechnung - kompiliere sie zu WASM und rufe sie aus JavaScript auf. Miss den Unterschied. Dann entscheide, wo WASM noch helfen kann.424425Das Tooling ist ausgereift, die Browser-Unterstutzung ist universell und das Okosystem wachst. Wenn du Rust schreibst, bist du bereits einen Befehl vom Browser entfernt.426427> **Einstiegs-Checkliste:**428>429> - [x] Rust und wasm-pack installiert430> - [x] Erstes WASM-Modul gebaut und im Browser laufend431> - [x] JavaScript-Interop funktioniert (WASM aus JS aufrufen)432> - [x] Release-Build mit Grossenoptimierungen angewendet433> - [x] Leistung gegen reines JavaScript-Aquivalent gemessen434> - [x] WASI mit Wasmtime fur serverseitige Anwendungsfalle erkundet435
:WebAssembly fur Webentwickler: Von Null zur Produktionlines 1-435 (END) — press q to close