spinny:~/writing $ less webassembly-wasm-complete-guide.md
12WebAssembly (WASM) startede som en made at kore C++ i browseren. I 2026 korer det overalt - browsere, servere, edge-netvaerk, indlejrede enheder - og driver nogle af de mest kraevenede applikationer pa nettet. Figmas rendering-motor, Adobe Photoshop pa nettet, Google Meets videobehandling og Cloudflares edge-compute-platform korer alle pa WebAssembly.34Chrome Platform Status angiver WASM til cirka 5,5 % af alle Chrome-sideindlaesninger i begyndelsen af 2026, op fra 4,5 % aret for. Med WASM 3.0 som W3C-standard og WASI pa vej mod version 1.0 har okosystemet naet et vendepunkt.56Denne guide daekker alt, du skal vide for at begynde at bygge med WebAssembly.78## Hvad er WebAssembly?910WebAssembly er et binaert instruktionsformat designet som kompileringsmal. Du skriver kode i et hojniveausprog (Rust, C, C++, Go, Kotlin), kompilerer det til `.wasm` og korer det i ethvert miljo, der har en WASM-runtime - browsere, Node.js, Cloudflare Workers, Wasmtime eller 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### Hvordan det virker2324WASM er en **stakbaseret virtuel maskine**. Funktioner skubber vaerdier pa en operandstk og fjerner dem igen. Vaerts-runtime:en (V8 i Chrome, SpiderMonkey i Firefox) JIT-kompilerer WASM-bytekoden til nativ maskinkode, hvilket er grunden til, at ydeevnen er naesten nativ.2526Vigtige egenskaber:2728- **Sandboxet eksekvering**: WASM-moduler kan kun fa adgang til ressourcer, som vaerten eksplicit giver. Intet filsystem, intet netvaerk, ingen OS-adgang medmindre det er tilladt. Dette er fundamentalt anderledes end nativ kode.29- **Lineaer hukommelse**: en enkelt sammenhaengende `ArrayBuffer`, der deles mellem WASM og vaerten. Komplekse data (strenge, structs) sendes ved at skrive til hukommelsen og dele en pointer.30- **Typebegraenset**: WASM understotter nativt kun fire typer: `i32`, `i64`, `f32`, `f64`. Alt andet (strenge, arrays, objekter) kraever kodning via lineaer hukommelse eller Component Model.31- **Portabelt**: den samme `.wasm`-binaerfil korer pa enhver platform med en WASM-runtime, uden rekompilering.3233### WASM vs JavaScript3435WASM erstatter ikke JavaScript. Det supplerer det.3637| Aspekt | JavaScript | WebAssembly |38|--------|-----------|-------------|39| **Parsing** | Parse + kompiler ved korsel | Praekompileret binaerfil, kun afkodning |40| **Eksekveringshastighed** | JIT-optimeret, variabel | Naesten nativ, konsistent |41| **Opstartstid** | Hurtig for sma scripts | Hurtig afkodning, forudsigelig |42| **DOM-adgang** | Direkte | Indirekte (via JS-gluekode) |43| **Bedst til** | UI, DOM-manipulation, event-handtering | CPU-intensive beregninger |44| **Garbage collection** | Indbygget | WasmGC (ny) eller manuel |4546Brug JavaScript til UI- og DOM-arbejde. Brug WASM til tunge beregninger: billedbehandling, videokodning, fysiksimulationer, kryptografi, databehandling.4748## WASM 3.0: hvad er nyt4950WebAssembly 3.0 blev en W3C-standard i september 2025 og standardiserede ni funktioner, der havde vaeret under udvikling i arevis.5152| Funktion | Hvad den muliggor |53|---------|----------------|54| **WasmGC** | Nativ garbage collection i WASM. Styrede sprog (Java, Kotlin, Dart) kan kompilere til WASM uden at medbringe deres egen GC-runtime. Understottet i Chrome 119+, Firefox 120+, Safari 18.2+. |55| **Exception Handling** | Nativt `try`/`catch` i WASM. Tidligere kraevede exceptions dyre rundture til JavaScript. |56| **Tail Calls** | Muliggor effektiv rekursion uden stack overflow. Afgurende for funktionelle sprog. |57| **Relaxed SIMD** | 128-bit vektorinstruktioner til parallel databehandling. Muliggor hardwarespecifikke optimeringer. |58| **Memory64** | Bryder gennem 4 GB-graensen for lineaer hukommelse. Nodvendigt for storskala databehandling. |59| **Multi-memory** | Flere uafhaengige hukommelsesregioner i et modul. |6061Den mest virkningsfulde er **WasmGC**. Tidligere betod kompilering af Java eller Kotlin til WASM, at man sendte en hel garbage collector som en del af binaerfilen, hvilket opblaste filstorrelserne. Nu handler browserens egen GC hukommelsesstyringen for WASM-moduler, lige som den gor for JavaScript.6263## WASI: WebAssembly ud over browseren6465WASM i browseren er kraftfuldt, men **WASI (WebAssembly System Interface)** er det, der gor WASM til en universel runtime. WASI leverer standardiserede graenseflader for systemressourcer - filer, netvaerk, ure, tilfaeldige tal - og muliggor, at WASM-moduler kan kore uden for browseren.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 (den nuvaerende stabile udgivelse) definerer disse graenseflader:8485- `wasi:filesystem` - filoperationer via capability-handles (ikke traditionelle fildeskriptorer)86- `wasi:sockets` - TCP/UDP-netvaerk87- `wasi:http` - HTTP-request/response-handtering88- `wasi:clocks` - vaegur, monotont ur89- `wasi:random` - kryptografisk tilfaeldighed90- `wasi:cli` - kommandolinjeargumenter, miljovariabler, stdio9192Nogleprincippet er **capability-baseret sikkerhed**: et WASM-modul kan ikke fa adgang til filsystemet, medmindre vaerten eksplicit giver et handle til en specifik mappe. Dette gor WASI fundamentalt sikrere end at kore native eksekverbare filer.9394### Vejen til WASI 1.09596WASI 0.3.0 (med tilfoejelse af async/concurrency-primitiver) forventes i 2026, med WASI 1.0 derefter. Den vigtigste nyhed er sprogintegreret async med zero-copy streaming I/O.9798## Component Model99100Kerne-WASM-moduler kan kun udveksle tal. **Component Model** loser denne begraensning ved at tilfoeje et rigt typesystem og et kompositionslag oven pa WASM.101102### WIT (WebAssembly Interface Types)103104WIT er et Interface Definition Language, der lader komponenter deklarere deres imports og exports med rige typer - strenge, records, lister, varianter, enums - ikke kun `i32` og `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 som `wit-bindgen` genererer sprogspecifikke bindings fra WIT-filer. En Rust-komponent og en Python-komponent kan udveksle strenge, records og lister gennem WIT-kontrakter, uden at nogen af siderne behover at kende den andens implementeringssprog.128129## Byg dit forste WASM-modul med Rust130131Rust har den mest modne WASM-tooling. Lad os bygge et praktisk eksempel: et billedbehandlingsmodul, der korer i browseren.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### Konfigurer Cargo.toml148149```toml150[package]151name = "image-processor"152version = "0.1.0"153edition = "2021"154155[lib]156crate-type = ["cdylib"]157158[dependencies]159wasm-bindgen = "0.2"160```161162### Skriv Rust-koden163164```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```227228Dette producerer en `pkg/`-mappe med:229- `image_processor_bg.wasm` - den kompilerede WASM-binaerfil230- `image_processor.js` - JavaScript-gluekode med TypeScript-definitioner231- `package.json` - klar til publicering pa npm232233### Brug i 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```285286Den centrale indsigt: `imageData.data` er et `Uint8ClampedArray` understottet af en `ArrayBuffer`. Nar det sendes til WASM, deler det den samme hukommelse - ingen kopiering. Rust-funktionen aendrer pixels direkte, og JavaScript-siden ser aendringerne ojeblikkeligt.287288## Lavere niveau: manuel WASM-instantiering289290Hvis du ikke onsker at bruge `wasm-bindgen`, kan du instantiere WASM-moduler direkte: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```306307Dette er nyttigt, nar du onsker minimal overhead og ikke behover rig type-interop.308309## Ydeevne: WASM vs JavaScript310311Virkelige benchmarks viser betydelige hastighedsforbedringer for CPU-intensive opgaver:312313| Opgave | JavaScript | WASM | Hastighedsforhoejelse |314|--------|-----------|------|---------|315| 4K-billedbehandling | 180ms | 8ms (med SIMD) | 22x |316| Billedskalering (4K) | 250ms | 45ms | 5,5x |317| Fysiksimulering (10K entiteter) | Taber frames | Javaevnt 60fps | ~10x |318| JSON-parsing (stor payload) | 12ms | 3ms | 4x |319| Kryptografisk hashing | 45ms | 6ms | 7,5x |320321WASM korer med cirka 95 % af nativ kodehastighed. De storste gevinster kommer fra:322- Forudsigelig ydeevne (ingen JIT-opvarmning, ingen GC-pauser)323- SIMD-instruktioner til parallel databehandling324- Direkte hukommelsesadgang uden garbage collector-interferens325326Hvor WASM IKKE er hurtigere: DOM-manipulation, sma beregninger, I/O-bundne opgaver. JavaScript er allerede optimeret til disse.327328## Produktionsanvendelser329330### Figma: realtids-vektorrendering331332Figmas kerne-rendering-motor er C++ kompileret til WASM. Enhver form, gradient og effekt beregnes i WASM og tegnes pa et Canvas-element. Dette gor det muligt for Figma at handtere komplekse designs med tusindvis af lag ved 60fps i browseren - ydeevne, der ville vaere umulig i rent JavaScript.333334### Adobe Photoshop pa nettet335336Adobe porterede vigtige Photoshop-filtre og -vaerktojer til WASM med Rust. Deres benchmarks viser 4K-billedbehandling pa 22ms med WASM SIMD mod 180ms i JavaScript - en 8x forbedring, der gor realtids-filterforhandsvisninger mulige.337338### Cloudflare Workers339340Cloudflare korer WASM-moduler i V8-isolates pa over 330 edge-lokationer. Cold starts er 1-5ms (sammenlignet med 100-500ms for containerbaseret serverless). I februar 2026 udrullede de Llama-3-8b-inferens over deres edge-netvaerk med WASM.341342### Google Meet343344Baggrundssluering og virtuelle baggrunde i Google Meet bruger WASM med SIMD til realtids-videobehandling. WASM-modulet behandler hvert videoframe hurtigt nok til at opretholde javaevn video ved 30fps.345346## Browserunderstottelse (2026)347348| Funktion | Chrome | Firefox | Safari | Edge |349|---------|--------|---------|--------|------|350| Core WASM | Fuld | Fuld | Fuld | Fuld |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 | Delvis | Ja |356357Alle store browsere understotter WASM fuldt ud. De nyere funktioner (WasmGC, Exception Handling) har opnaet bred tilgaengelighed.358359## Tooling-reference360361| Vaerktoej | Formal | Installation |362|------|---------|---------|363| **wasm-pack** | Byg Rust til WASM, generer npm-pakker | `cargo install wasm-pack` |364| **wasm-bindgen** | Rust/JS-interop-bindings (brugt af wasm-pack) | Dependency i Cargo.toml |365| **wasm-opt** | Optimering af binaerfilstorrelse (50%+ reduktion) | Del af Binaryen: `brew install binaryen` |366| **wit-bindgen** | Generer bindings fra WIT-filer | `cargo install wit-bindgen-cli` |367| **Wasmtime** | Server-side WASM-runtime (reference-WASI-implementering) | `brew install wasmtime` |368| **Wasmer** | Alternativ WASM-runtime med WASI-understottelse | `curl https://get.wasmer.io -sSfL \| sh` |369| **wasm-feature-detect** | Runtime browser-funktionsdetektion | `npm install wasm-feature-detect` |370371### Optimering af binaerfilstorrelse372373WASM-binaerfiler kan vaere store. Sadan formindsker du dem: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```391392Et typisk Rust-WASM-modul gar fra 500KB til under 50KB med disse optimeringer.393394## Startroadmap395396```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## Konklusion420421WebAssembly er ikke laengere eksperimentelt. Det er en produktionsteknologi, der bruges af nogle af de mest kraevende applikationer pa nettet. Naesten nativ ydeevne, sandboxet sikkerhed og universel portabilitet - intet andet kompileringsmal giver dig alle tre.422423Du behover ikke omskrive hele din applikation i WASM. Start med en enkelt CPU-intensiv funktion - et billedfilter, en dataparser, en fysikberegning - kompiler den til WASM og kald den fra JavaScript. Mal forskellen. Beslu derefter, hvor WASM ellers kan hjaelpe.424425Toolingen er moden, browserunderstottelsen er universel, og okosystemet vokser. Hvis du skriver Rust, er du allerede en kommando fra browseren.426427> **Startcheckliste:**428>429> - [x] Rust og wasm-pack installeret430> - [x] Forste WASM-modul bygget og korende i browseren431> - [x] JavaScript-interop virker (kald WASM fra JS)432> - [x] Release-build med storrelsesoptimeringer anvendt433> - [x] Ydeevne benchmarket mod rent JavaScript-akvivalent434> - [x] WASI udforsket med Wasmtime til server-side anvendelser435
:WebAssembly for webudviklere: fra nul til produktionlines 1-435 (END) — press q to close