WebAssembly (WASM) zaczal jako sposob na uruchamianie C++ w przegladarce. W 2026 roku dziala wszedzie - przegladarki, serwery, sieci edge, urzadzenia wbudowane - i napedza jedne z najbardziej wymagajacych aplikacji w sieci. Silnik renderujacy Figmy, Adobe Photoshop w wersji webowej, przetwarzanie wideo Google Meet i platforma obliczen edge Cloudflare - wszystko dziala na WebAssembly.
Chrome Platform Status podaje, ze WASM stanowi okolo 5,5% wszystkich zaladowan stron w Chrome na poczatku 2026 roku, w porownaniu z 4,5% rok wczesniej. Wraz z tym, ze WASM 3.0 zostal standardem W3C, a WASI dojrzewa w kierunku wersji 1.0, ekosystem osiagnal punkt zwrotny.
Ten przewodnik obejmuje wszystko, co musisz wiedziec, zeby zaczac budowac z WebAssembly.
Czym jest WebAssembly?
WebAssembly to binarny format instrukcji zaprojektowany jako cel kompilacji. Piszesz kod w jezyku wysokiego poziomu (Rust, C, C++, Go, Kotlin), kompilujesz go do .wasm i uruchamiasz w dowolnym srodowisku posiadajacym runtime WASM - przegladarki, Node.js, Cloudflare Workers, Wasmtime lub Wasmer.
Jak to dziala
WASM to maszyna wirtualna oparta na stosie. Funkcje umieszczaja i pobieraja wartosci ze stosu operandow. Runtime hosta (V8 w Chrome, SpiderMonkey w Firefoksie) kompiluje JIT bajtkod WASM do natywnego kodu maszynowego, dlatego wydajnosc jest bliska natywnej.
Kluczowe cechy:
- Wykonanie w piaskownicy: moduly WASM moga uzyskac dostep tylko do zasobow, ktore host jawnie przyznaje. Brak dostepu do systemu plikow, sieci ani systemu operacyjnego, chyba ze zostanie to dozwolone. To fundamentalna roznica w porownaniu z kodem natywnym.
- Pamiec liniowa: pojedynczy ciagly
ArrayBufferwspoldzielony miedzy WASM a hostem. Zlezone dane (stringi, struktury) sa przekazywane przez zapis do pamieci i udostepnienie wskaznika. - Ograniczone typy: WASM natywnie obsluguje tylko cztery typy:
i32,i64,f32,f64. Wszystko inne (stringi, tablice, obiekty) wymaga kodowania przez pamiec liniowa lub Component Model. - Przenosnosc: ten sam plik binarny
.wasmdziala na dowolnej platformie z runtime WASM, bez rekompilacji.
WASM vs JavaScript
WASM nie zastepuje JavaScriptu. Uzupelnia go.
| Aspekt | JavaScript | WebAssembly |
|---|---|---|
| Parsowanie | Parsowanie + kompilacja w runtime | Wstepnie skompilowany plik binarny, tylko dekodowanie |
| Szybkosc wykonania | Zoptymalizowany JIT, zmienny | Blisko natywny, stalej jakosci |
| Start | Szybki dla malych skryptow | Szybkie dekodowanie, przewidywalny |
| Dostep do DOM | Bezposredni | Posredni (przez warstwe JS) |
| Najlepszy do | UI, manipulacja DOM, obsluga zdarzen | Intensywne obliczenia CPU |
| Odsmiecanie pamieci | Wbudowane | WasmGC (nowe) lub reczne |
Uzywaj JavaScriptu do pracy z UI i DOM. Uzywaj WASM do ciezkich obliczen: przetwarzanie obrazow, kodowanie wideo, symulacje fizyczne, kryptografia, parsowanie danych.
WASM 3.0: co nowego
WebAssembly 3.0 zostal standardem W3C we wrzesniu 2025 roku, standaryzujac dziewiec funkcji, ktore byly rozwijane przez lata.
| Funkcja | Co umozliwia |
|---|---|
| WasmGC | Natywne odsmiecanie pamieci w WASM. Jezyki zarzadzane (Java, Kotlin, Dart) moga kompilowac do WASM bez dolaczania wlasnego runtime GC. Obslugiwane w Chrome 119+, Firefox 120+, Safari 18.2+. |
| Exception Handling | Natywne try/catch w WASM. Wczesniej wyjatki wymagaly kosztownych przejsc do JavaScriptu. |
| Tail Calls | Umozliwia efektywna rekurencje bez przepelnienia stosu. Kluczowe dla jezykow funkcyjnych. |
| Relaxed SIMD | 128-bitowe instrukcje wektorowe do rownoleglego przetwarzania danych. Umozliwia optymalizacje specyficzne dla sprzetu. |
| Memory64 | Przełamuje limit 4GB pamieci liniowej. Wymagane do przetwarzania danych na duza skale. |
| Multi-memory | Wiele niezaleznych regionow pamieci w jednym module. |
Najbardziej przelomowy jest WasmGC. Wczesniej kompilacja Javy lub Kotlina do WASM oznaczala dolaczenie calego garbage collectora jako czesci pliku binarnego, co znacznie zwiększalo rozmiar plikow. Teraz wlasny GC przegladarki zarzadza pamiecia modulow WASM, tak jak robi to dla JavaScriptu.
WASI: WebAssembly poza przegladarka
WASM w przegladarce jest potezny, ale WASI (WebAssembly System Interface) sprawia, ze WASM staje sie uniwersalnym runtime. WASI zapewnia znormalizowane interfejsy do zasobow systemowych - pliki, siec, zegary, liczby losowe - umozliwiajac uruchamianie modulow WASM poza przegladarka.
WASI Preview 2 (obecne stabilne wydanie) definiuje nastepujace interfejsy:
wasi:filesystem- operacje na plikach za pomoca uchwytow uprawnien (nie tradycyjnych deskryptorow plikow)wasi:sockets- siec TCP/UDPwasi:http- obsluga zadan/odpowiedzi HTTPwasi:clocks- zegar scienny, zegar monotonicznywasi:random- kryptograficzna losowoscwasi:cli- argumenty wiersza polecen, zmienne srodowiskowe, stdio
Kluczowa zasada to bezpieczenstwo oparte na uprawnieniach: modul WASM nie moze uzyskac dostepu do systemu plikow, chyba ze host jawnie przyznaje uchwyt do okreslonego katalogu. To sprawia, ze WASI jest fundamentalnie bezpieczniejszy niz uruchamianie natywnych plikow wykonywalnych.
Droga do WASI 1.0
WASI 0.3.0 (dodajacy prymitywy async/wspolbieznosci) jest oczekiwany w 2026 roku, a WASI 1.0 ma nastapic potem. Glownym dodatkiem jest zintegrowane z jezykiem async z bezkopiowym strumieniowym I/O.
Component Model
Podstawowe moduly WASM moga wymieniac tylko liczby. Component Model rozwiazuje to ograniczenie, dodajac bogaty system typow i warstwe kompozycji na szczycie WASM.
WIT (WebAssembly Interface Types)
WIT to jezyk definicji interfejsow, ktory pozwala komponentom deklarowac importy i eksporty z bogatymi typami - stringi, rekordy, listy, warianty, enumy - nie tylko i32 i f64.
// calculator.wit package myorg:calculator@1.0.0; interface operations { record calculation { expression: string, result: f64, timestamp: u64, } add: func(a: f64, b: f64) -> f64; multiply: func(a: f64, b: f64) -> f64; history: func() -> list<calculation>; } world calculator { export operations; }
Lancuchy narzedzi takie jak wit-bindgen generuja powiazania specyficzne dla jezyka z plikow WIT. Komponent w Rust i komponent w Pythonie moga wymieniac stringi, rekordy i listy poprzez kontrakty WIT, bez koniecznosci znajomosci jezyka implementacji drugiej strony.
Budowanie pierwszego modulu WASM z Rust
Rust ma najbardziej dojrzale narzedzia WASM. Zbudujmy praktyczny przyklad: modul przetwarzania obrazow dzialajacy w przegladarce.
Konfiguracja
# Install the WASM target for Rust rustup target add wasm32-unknown-unknown # Install wasm-pack (builds Rust to WASM + generates JS bindings) cargo install wasm-pack # Create a new library project cargo new --lib image-processor cd image-processor
Konfiguracja Cargo.toml
[package] name = "image-processor" version = "0.1.0" edition = "2021" [lib] crate-type = ["cdylib"] [dependencies] wasm-bindgen = "0.2"
Napisz kod Rust
// src/lib.rs use wasm_bindgen::prelude::*; /// Convert an image buffer to grayscale. /// Input: RGBA pixel data as a flat u8 array (4 bytes per pixel). /// Output: Modified in place for zero-copy performance. #[wasm_bindgen] pub fn grayscale(pixels: &mut [u8]) { for chunk in pixels.chunks_exact_mut(4) { let r = chunk[0] as f32; let g = chunk[1] as f32; let b = chunk[2] as f32; // ITU-R BT.709 luminance coefficients let gray = (0.2126 * r + 0.7152 * g + 0.0722 * b) as u8; chunk[0] = gray; chunk[1] = gray; chunk[2] = gray; // chunk[3] is alpha, leave unchanged } } /// Adjust brightness of an image. /// factor > 1.0 brightens, < 1.0 darkens. #[wasm_bindgen] pub fn adjust_brightness(pixels: &mut [u8], factor: f32) { for chunk in pixels.chunks_exact_mut(4) { chunk[0] = ((chunk[0] as f32 * factor).min(255.0)) as u8; chunk[1] = ((chunk[1] as f32 * factor).min(255.0)) as u8; chunk[2] = ((chunk[2] as f32 * factor).min(255.0)) as u8; } } /// Invert all colors in the image. #[wasm_bindgen] pub fn invert(pixels: &mut [u8]) { for chunk in pixels.chunks_exact_mut(4) { chunk[0] = 255 - chunk[0]; chunk[1] = 255 - chunk[1]; chunk[2] = 255 - chunk[2]; } } /// Calculate the average brightness of an image (0-255). #[wasm_bindgen] pub fn average_brightness(pixels: &[u8]) -> f32 { let mut total: f64 = 0.0; let pixel_count = pixels.len() / 4; for chunk in pixels.chunks_exact(4) { let luminance = 0.2126 * chunk[0] as f64 + 0.7152 * chunk[1] as f64 + 0.0722 * chunk[2] as f64; total += luminance; } (total / pixel_count as f64) as f32 }
Budowanie
wasm-pack build --target web
To tworzy katalog pkg/ zawierajacy:
image_processor_bg.wasm- skompilowany plik binarny WASMimage_processor.js- kod laczacy JavaScript z definicjami TypeScriptpackage.json- gotowy do publikacji w npm
Uzycie w JavaScript
<!DOCTYPE html> <html> <head><title>WASM Image Processor</title></head> <body> <canvas id="canvas" width="800" height="600"></canvas> <button onclick="applyGrayscale()">Grayscale</button> <button onclick="applyBrightness()">Brighten</button> <button onclick="applyInvert()">Invert</button> <script type="module"> import init, { grayscale, adjust_brightness, invert } from "./pkg/image_processor.js"; let ctx; let imageData; async function setup() { await init(); const canvas = document.getElementById("canvas"); ctx = canvas.getContext("2d"); // Load an image onto the canvas const img = new Image(); img.onload = () => { ctx.drawImage(img, 0, 0); imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); }; img.src = "photo.jpg"; } window.applyGrayscale = () => { grayscale(imageData.data); ctx.putImageData(imageData, 0, 0); }; window.applyBrightness = () => { adjust_brightness(imageData.data, 1.3); ctx.putImageData(imageData, 0, 0); }; window.applyInvert = () => { invert(imageData.data); ctx.putImageData(imageData, 0, 0); }; setup(); </script> </body> </html>
Kluczowy wniosek: imageData.data to Uint8ClampedArray oparty na ArrayBuffer. Przy przekazywaniu do WASM wspoldziela te sama pamiec - bez kopiowania. Funkcja Rust modyfikuje piksele w miejscu, a strona JavaScript natychmiast widzi zmiany.
Nizszy poziom: reczna instancjacja WASM
Jesli nie chcesz uzywac wasm-bindgen, mozesz bezposrednio tworzyc instancje modulow WASM:
const response = await fetch("calculator.wasm"); const { instance } = await WebAssembly.instantiateStreaming(response, { env: { // Functions the WASM module can call log_result: (value) => console.log("Result:", value), }, }); // Call exported functions const { add, multiply } = instance.exports; console.log(add(5, 3)); // 8 console.log(multiply(4, 7)); // 28
Jest to przydatne, gdy chcesz minimalnego narzutu i nie potrzebujesz bogatego interop typow.
Wydajnosc: WASM vs JavaScript
Rzeczywiste benchmarki pokazuja znaczne przyspieszenia dla zadan intensywnie obciazajacych CPU:
| Zadanie | JavaScript | WASM | Przyspieszenie |
|---|---|---|---|
| Przetwarzanie obrazu 4K | 180ms | 8ms (z SIMD) | 22x |
| Zmiana rozmiaru obrazu (4K) | 250ms | 45ms | 5,5x |
| Symulacja fizyczna (10K obiektow) | Utrata klatek | Plynne 60fps | ~10x |
| Parsowanie JSON (duzy payload) | 12ms | 3ms | 4x |
| Hashowanie kryptograficzne | 45ms | 6ms | 7,5x |
WASM dziala z okolo 95% predkosci kodu natywnego. Najwieksze zyski wynikaja z:
- Przewidywalnej wydajnosci (brak rozgrzewki JIT, brak pauz GC)
- Instrukcji SIMD do rownoleglego przetwarzania danych
- Bezposredniego dostepu do pamieci bez ingerencji garbage collectora
Gdzie WASM NIE jest szybszy: manipulacja DOM, male obliczenia, zadania ograniczone przez I/O. JavaScript jest juz do tego zoptymalizowany.
Przypadki uzycia produkcyjnego
Figma: renderowanie wektorow w czasie rzeczywistym
Glowny silnik renderujacy Figmy to C++ skompilowany do WASM. Kazdy ksztalt, gradient i efekt jest obliczany w WASM i rysowany na elemencie Canvas. Pozwala to Figmie obslugiwac zlozone projekty z tysiacami warstw przy 60fps w przegladarce - wydajnosc, ktora bylaby niemozliwa w czystym JavaScripcie.
Adobe Photoshop w przegladarce
Adobe przenioslo kluczowe filtry i narzedzia Photoshopa do WASM przy uzyciu Rust. Ich benchmarki pokazuja przetwarzanie obrazu 4K w 22ms z WASM SIMD vs 180ms w JavaScripcie - 8-krotna poprawa, ktora umozliwia podglad filtrow w czasie rzeczywistym.
Cloudflare Workers
Cloudflare uruchamia moduly WASM w izolatach V8 w ponad 330 lokalizacjach edge. Zimne starty trwaja 1-5ms (w porownaniu ze 100-500ms dla serverless opartego na kontenerach). W lutym 2026 roku wdrozyli wnioskowanie Llama-3-8b w calej sieci edge przy uzyciu WASM.
Google Meet
Rozmycie tla i wirtualne tla w Google Meet uzywaja WASM z SIMD do przetwarzania wideo w czasie rzeczywistym. Modul WASM przetwarza kazda klatke wideo wystarczajaco szybko, aby utrzymac plynne wideo przy 30fps.
Obsluga przegladarek (2026)
| Funkcja | Chrome | Firefox | Safari | Edge |
|---|---|---|---|---|
| Core WASM | Pelna | Pelna | Pelna | Pelna |
| Threads | Tak | Tak | Tak | Tak |
| SIMD (128-bit) | Tak | Tak | Tak | Tak |
| WasmGC | 119+ | 120+ | 18.2+ | Tak |
| Exception Handling | Tak | Tak | Tak | Tak |
| Memory64 | Tak | Tak | Czesciowo | Tak |
Wszystkie glowne przegladarki w pelni obsluguja WASM. Nowsze funkcje (WasmGC, Exception Handling) osiagnely szeroka dostepnosc.
Referencje narzedzi
| Narzedzie | Przeznaczenie | Instalacja |
|---|---|---|
| wasm-pack | Budowanie Rust do WASM, generowanie pakietow npm | cargo install wasm-pack |
| wasm-bindgen | Powiazania interop Rust/JS (uzywane przez wasm-pack) | Zaleznosc w Cargo.toml |
| wasm-opt | Optymalizacja rozmiaru pliku binarnego (50%+ redukcji) | Czesc Binaryen: brew install binaryen |
| wit-bindgen | Generowanie powiazan z plikow WIT | cargo install wit-bindgen-cli |
| Wasmtime | Serwerowy runtime WASM (referencyjna implementacja WASI) | brew install wasmtime |
| Wasmer | Alternatywny runtime WASM z obsluga WASI | curl https://get.wasmer.io -sSfL | sh |
| wasm-feature-detect | Wykrywanie funkcji przegladarki w runtime | npm install wasm-feature-detect |
Optymalizacja rozmiaru pliku binarnego
Pliki binarne WASM moga byc duze. Oto jak je zmniejszyc:
# Cargo.toml [profile.release] opt-level = "z" # Optimize for size lto = true # Link-time optimization codegen-units = 1 # Better optimization, slower compile strip = true # Strip debug symbols
# Build in release mode wasm-pack build --release --target web # Further optimize with wasm-opt wasm-opt -Oz pkg/image_processor_bg.wasm -o pkg/image_processor_bg.wasm
Typowy modul Rust WASM zmniejsza sie z 500KB do ponizej 50KB przy tych optymalizacjach.
Plan dzialania na start
Podsumowanie
WebAssembly nie jest juz technologia eksperymentalna. To technologia produkcyjna uzywana przez jedne z najbardziej wymagajacych aplikacji w sieci. Wydajnosc bliska natywnej, bezpieczenstwo piaskownicy i uniwersalna przenosnosc - zaden inny cel kompilacji nie daje wszystkich trzech jednoczesnie.
Nie musisz przepisywac calej aplikacji w WASM. Zacznij od pojedynczej funkcji intensywnie obciazajacej CPU - filtra obrazu, parsera danych, obliczen fizycznych - skompiluj ja do WASM i wywolaj z JavaScriptu. Zmierz roznice. Potem zdecyduj, gdzie jeszcze WASM moze pomoc.
Narzedzia sa dojrzale, obsluga przegladarek jest uniwersalna, a ekosystem rosnie. Jesli piszesz w Rust, jestes juz o jedno polecenie od przegladarki.
Lista kontrolna na start:
- Rust i wasm-pack zainstalowane
- Pierwszy modul WASM zbudowany i uruchomiony w przegladarce
- Interop z JavaScript dziala (wywoływanie WASM z JS)
- Wersja release z optymalizacjami rozmiaru zastosowana
- Wydajnosc porownana z odpowiednikiem w czystym JavaScripcie
- WASI zbadane z Wasmtime dla przypadkow uzycia po stronie serwera