Перейти к основному содержимому

WebAssembly (WASM) — что это и когда использовать

Разработчику Архитектору

WebAssembly (WASM)

WebAssembly (WASM) — бинарный формат и виртуальная машина для быстрого и предсказуемого кода рядом с JavaScript в браузере и за его пределами:

  • Node.js;
  • edge-вычисления (Cloudflare Workers, Fastly Compute);
  • плагины в sandbox (Wasmer, Wasmtime).

WASM дополняет JS: UI, сеть и DOM — на JS/TS, тяжёлые вычисления — на WASM.

Общая база про компиляцию и байт-код помогает понять, почему WASM ближе к машинному коду, чем к исходнику Python.

ШагТемаРезультат
1Термины и формат .wasmПонимание, что внутри модуля
2Загрузка в браузереМинимальный JS + WASM
3Rust + wasm-bindgenРеальный проект
4Сравнение с JSКогда ускорение оправдано
5WASM вне браузераNode, Wasmer, edge
С чего начать новичку

Если вы ещё не прошли первую программу на Node.js и базовый JavaScript, начните с них. WASM всегда работает в паре с JS или другим хостом — без понимания JS загрузка модуля будет непонятной.


Глоссарий терминов

ТерминПростое объяснение
WASM / WebAssemblyОткрытый стандарт бинарного формата и виртуальной машины для быстрого кода
Модуль .wasmСкомпилированный файл с функциями, памятью и таблицами
Linear memoryОдин непрерывный массив байт, общий между WASM и хостом
Export / ImportФункции и память, которые модуль отдаёт наружу или получает от хоста
InstantiateСоздание работающего экземпляра модуля в runtime
JIT / AOTJust-in-time — компиляция при запуске; ahead-of-time — заранее
wasm-bindgenИнструмент Rust для генерации JS-обёрток
EmscriptenКомпилятор C/C++ в WASM
Source mapКарта соответствия скомпилированного кода исходникам для отладки
SandboxИзолированная среда без прямого доступа к файлам и сети
HostПрограмма, которая загружает WASM (браузер, Node.js, Wasmtime)

Что такое WASM

СвойствоОписание
ФорматКомпактный .wasm — секции типов, функций, памяти, экспортов
ВыполнениеJIT/AOT в браузере (V8, SpiderMonkey, JavaScriptCore) или wasmtime/wasmer
ЯзыкиRust, C/C++, Go, C# (Blazor), AssemblyScript, Zig и др.
ПамятьЛинейная память (WebAssembly.Memory); обмен с JS через API
БезопасностьSandbox как у JS — без прямого доступа к DOM и файловой системе

WASM не имеет DOM API. Модуль экспортирует функции; JS вызывает их и копирует данные через WebAssembly.Memory.

Структура модуля .wasm

Бинарный файл состоит из секций (упрощённо):

  • Type — сигнатуры функций (какие аргументы и возвращаемые значения);
  • Function — индексы функций;
  • Memory — описание линейной памяти;
  • Export — что доступно снаружи (add, memory, …);
  • Code — тело функций в байт-коде WASM.

Текстовое представление — WAT (WebAssembly Text Format). Его можно читать и писать вручную для обучения, но в production обычно генерируют компилятором.

Пример WAT (сложение двух чисел):

(module
(func (export "add") (param i32 i32) (result i32)
local.get 0
local.get 1
i32.add)
)

Компиляция в .wasm:

wat2wasm add.wat -o add.wasm

Инструмент wat2wasm входит в пакет WABT.


Как браузер выполняет WASM

Этапы подробнее:

  1. Fetch — браузер скачивает .wasm по HTTP(S). Нужен корректный MIME-тип application/wasm.
  2. Compile — движок парсит секции и компилирует в машинный код (часто параллельно с загрузкой).
  3. Instantiate — создаётся instance с exports и подключаются imports из JS.
  4. Call — JS вызывает экспортированные функции; данные передаются как числа или через память.
instantiateStreaming

WebAssembly.instantiateStreaming(fetch(url), imports) начинает компиляцию до полной загрузки файла — быстрее, чем fetch + instantiate по отдельности. Требует корректного Content-Type на сервере.


Связь с JavaScript

Типичный поток в браузере:

index.html
└── app.js (загрузка, UI, fetch)
└── instantiateStreaming(fetch('module.wasm'))
└── wasm exports: add, process_buffer, ...

Минимальный HTML + JS

index.html:

<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="utf-8">
<title>WASM demo</title>
</head>
<body>
<p>Результат: <span id="out"></span></p>
<script type="module" src="app.js"></script>
</body>
</html>

app.js:

async function main() {
const response = await fetch('/add.wasm');
if (!response.ok) throw new Error(`HTTP ${response.status}`);

const { instance } = await WebAssembly.instantiateStreaming(response, {});
const sum = instance.exports.add(2, 3);
document.getElementById('out').textContent = String(sum);
}

main().catch(console.error);

Разбор:

  • fetch возвращает Response с телом .wasm;
  • instantiateStreaming компилирует и создаёт instance;
  • instance.exports.add — функция из WAT/WASM модуля;
  • DOM обновляет только JS — WASM не трогает HTML напрямую.

Передача строк и объектов

JS передаёт в WASM в основном числа (i32, i64, f32, f64). Для строк и структур:

  • копируют байты в linear memory и передают смещение и длину;
  • используют библиотеки glue-кода (wasm-bindgen, Emscripten, wit-bindgen).

Без glue вручную нужно согласовать layout байт (кодировка UTF-8, выравнивание).


Практикум 1 — WAT вручную

Шаг 1. Установка WABT

Linux (Debian/Ubuntu):

sudo apt install wabt

macOS:

brew install wabt

Windows: скачайте бинарники с релизов WABT или используйте WSL.

Проверка:

wat2wasm --version

Шаг 2. Файл add.wat

Создайте add.wat (см. пример выше в разделе "Структура модуля").

Шаг 3. Сборка

wat2wasm add.wat -o add.wasm

Шаг 4. Локальный сервер

Браузер не откроет fetch с file:// — нужен HTTP. Из папки проекта:

npx serve .

или Python:

python -m http.server 8080

Откройте http://localhost:8080 — в #out должно быть 5.

Шаг 5. Отладка в DevTools

Chrome → SourcesWebAssembly → откройте add.wasm, поставьте breakpoint на add. Перезагрузите страницу — выполнение остановится внутри WASM.


Rust → WASM (полный практикум)

Популярный production-путь — wasm-pack + wasm-bindgen.

Подготовка

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
rustup target add wasm32-unknown-unknown
cargo install wasm-pack

Проверка:

rustc --version
wasm-pack --version

Шаг 1. Создание библиотеки

cargo new --lib wasm-demo
cd wasm-demo

Шаг 2. Cargo.toml

[package]
name = "wasm-demo"
version = "0.1.0"
edition = "2021"

[lib]
crate-type = ["cdylib"]

[dependencies]
wasm-bindgen = "0.2"

cdylib — динамическая библиотека для WASM, без Rust runtime в финальном модуле.

Шаг 3. src/lib.rs

use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub fn add(a: i32, b: i32) -> i32 {
a + b
}

#[wasm_bindgen]
pub fn fib(n: u32) -> u32 {
match n {
0 => 0,
1 => 1,
_ => fib(n - 1) + fib(n - 2),
}
}

#[wasm_bindgen] генерирует JS-обёртки при сборке.

Шаг 4. Сборка для web

wasm-pack build --target web

Артефакты в pkg/:

  • wasm_demo_bg.wasm — модуль;
  • wasm_demo.js — glue-код;
  • wasm_demo.d.ts — типы для TypeScript.

Шаг 5. Подключение в Vite

Создайте проект Vite:

npm create vite@latest wasm-vite -- --template vanilla-ts
cd wasm-vite

Скопируйте pkg/ в src/wasm-demo/. В main.ts:

import init, { add, fib } from './wasm-demo/wasm_demo.js';

async function run() {
await init();
console.log('add(2, 3) =', add(2, 3));
console.time('fib-wasm');
console.log('fib(35) =', fib(35));
console.timeEnd('fib-wasm');
}

run();

init() загружает и инициализирует .wasm.

Шаг 6. Сравнение с JavaScript

В том же main.ts:

function fibJs(n: number): number {
if (n <= 1) return n;
return fibJs(n - 1) + fibJs(n - 2);
}

console.time('fib-js');
console.log('fibJs(35) =', fibJs(35));
console.timeEnd('fib-js');

На типичном ноутбуке WASM быстрее в 2–5 раз для fib(35). Для fib(40) разрыв ещё заметнее. Откройте Performance в DevTools и сравните flame chart.

Подходит для:

  • криптографии;
  • парсеров (JSON, protobuf, custom binary);
  • игровой физики;
  • обработки изображений и видео в браузере.

Плюсы Rust в WASM:

  • без GC в WASM-модуле;
  • контроль памяти;
  • предсказуемая производительность.

Минусы:

  • размер бандла (десятки–сотни KB даже для маленькой функции);
  • learning curve Rust;
  • отладка сложнее, чем чистый TS.

C и C++ через Emscripten

Legacy-код и библиотеки на C/C++ часто портируют через Emscripten — LLVM-бэкенд в WASM + JS glue.

Установка (кратко): следуйте официальному гайду Emscripten.

Пример hello.c:

#include <stdio.h>

int main() {
printf("Hello from Emscripten\n");
return 0;
}

Сборка:

emcc hello.c -o hello.html

Emscripten генерирует HTML + JS + WASM — можно открыть в браузере. Для интеграции с React/Vite обычно собирают только .wasm + минимальный glue.

Когда выбирают Emscripten:

  • портирование ffmpeg, SQLite, игровых движков;
  • reuse существующего C/C++ кода;
  • команда знает C++, но не Rust.

AssemblyScript

AssemblyScript — TypeScript-подобный синтаксис, компилируемый в WASM. Удобен, если вы знаете TS, но не хотите учить Rust.

npm install -g assemblyscript
npm init
npx asinit

assembly/index.ts:

export function add(a: i32, b: i32): i32 {
return a + b;
}

Сборка:

npm run asbuild

Ограничения: не весь TS — только подмножество, близкое к WASM-типам (i32, f64, …).


C# → WASM (Blazor)

.NET компилируется в WASM для Blazor WebAssembly — SPA на C# в браузере. Runtime .NET загружается один раз; приложение выполняется локально в браузере.

Blazor Server выполняет C# на сервере и стримит UI по SignalR — WASM не используется на клиенте.

КритерийBlazor WASMBlazor Server
Где выполняется C#браузерсервер
Первый загрузтяжёлый (скачивается .NET runtime)лёгкий
Офлайнвозможеннет
Масштабированиенагрузка на клиентнагрузка на сервер

Создание проекта:

dotnet new blazorwasm -o BlazorApp
cd BlazorApp
dotnet run

Для greenfield веб-UI чаще React/Vue/Svelte; Blazor — когда команда уже на .NET и хочет единый язык на клиенте и сервере.


Go → WASM

Go поддерживает GOOS=js GOARCH=wasm, но размер модулей historically был большим (мегабytes из-за runtime). Для tiny WASM модулей Go используют реже, чем Rust. Проверяйте актуальные размеры для вашей версии Go перед выбором.

GOOS=js GOARCH=wasm go build -o main.wasm main.go

Когда использовать WASM

СценарийWASMДостаточно JS
Видео/аудио кодеки, ffmpeg в браузереслабо
Редакторы (Figma-подобная графика)
Криптография, hashing больших данныхWeb Crypto API для простого
Игры 2D/3D (Unity, Godot export)Canvas для простого
Парсинг больших файлов на клиенте
Обычная форма и CRUD
SSR и SEO-страницы✓ HTML/JS
REST API на сервере✓ Node/Python/Go

Правило: профилируйте сначала. Преждевременный WASM усложняет сборку, CI и отладку. Если ArrayBuffer и Web Workers решают задачу — начните с них.


WASM вне браузера

Node.js

В Node.js глобальный объект WebAssembly доступен с версии 8+. Тот же API, что в браузере:

import { readFile } from 'node:fs/promises';

const bytes = await readFile('./add.wasm');
const { instance } = await WebAssembly.instantiate(bytes);
console.log(instance.exports.add(10, 20));

Use case: тяжёлые вычисления в worker threads, единый WASM-модуль для браузера и сервера.

Wasmer и Wasmtime

Wasmer и Wasmtime — standalone runtime для WASM:

  • sandbox-плагины (редакторы, CI);
  • serverless functions;
  • изоляция непроверенного кода.

Концепция близка к JVM/.NET CLR, но формат открыт и ориентирован на web-first.

Edge (Cloudflare Workers)

Cloudflare Workers поддерживают WASM-модули как расширения к JS. Проверяйте лимиты размера и API для вашего тарифа.


Безопасность и sandbox

WASM-модуль в браузере:

  • не читает файлы диска;
  • не открывает сокеты напрямую;
  • не трогает DOM;
  • получает только то, что передал host через imports.

Это та же модель доверия, что у JS — код из интернета выполняется в песочнице. Уязвимости в runtime (баги движка) возможны, как и для JS JIT.

Для секретов (API keys) — никогда не вшивайте в WASM; бинарник можно декомпилировать. Секреты — только на сервере.


Ограничения и эволюция стандарта

  • Нет прямого доступа к DOM — только через JS.
  • Отладка сложнее, чем в чистом TS (source maps и DWARF в WASM улучшают ситуацию).
  • Размер: Rust/.NET runtime + модуль могут быть мегабайты — нужен code splitting и lazy load.
  • Threads (SharedArrayMemory) — требуют заголовков COOP/COEP на сервере.
  • GC proposal — объектная модель в WASM; поддержка браузеров растёт — проверяйте caniuse.com/wasm.

Оптимизация размера бандла

ПриёмЭффект
wasm-opt (Binaryen)Уменьшает .wasm на 10–30%
LTO в Rust (RUSTFLAGS="-C link-arg=--gc-sections")Убирает мёртвый код
Lazy load WASMНе грузить модуль до первого использования
wee_alloc в RustМеньший аллокатор для tiny modules
Динамический import в ViteОтдельный chunk для WASM
# после wasm-pack build
wasm-opt -Oz pkg/wasm_demo_bg.wasm -o pkg/wasm_demo_bg.opt.wasm

Интеграция с TypeScript и Vite

В TypeScript проектах:

  • импортируйте glue из pkg/*.js;
  • типы из *.d.ts;
  • в vite.config.ts для некоторых пакетов нужен плагин vite-plugin-wasm — проверяйте документацию wasm-pack для вашей версии.

Типичная структура:

src/
wasm/
pkg/ # артеfact wasm-pack
main.ts
components/

CI: добавьте шаг wasm-pack build перед npm run build.


WASM Component Model (обзор)

Component Model — следующий уровень абстракции: композиция нескольких WASM-модулей с типизированными интерфейсами (WIT — WebAssembly Interface Types). Полезно для:

  • плагинных систем;
  • polyglot микросервисов в одном процессе;
  • стандартизации ABI между языками.

На 2025–2026 поддержка ещё набирает обороты — для учебных проектов достаточно классических модулей + wasm-bindgen.


Частые ошибки

СимптомПричинаРешение
CompileError при instantiateБитый .wasm или неверная версияПересоберите; проверьте file/wasm-validate
fetch failed / CORSНет сервера или CORSЛокальный serve; заголовки на CDN
instantiateStreaming failedMIME не application/wasmНастройте nginx/Apache
memory access out of boundsНеверное смещение в linear memoryПроверьте glue и размер буфера
Огромный бандлDebug build, без opt--release, wasm-opt -Oz
Rust panic в WASMunwrap на ошибкеconsole_error_panic_hook crate
Строки кракозябрамиНе UTF-8 в memoryКодировка и length в байтах

FAQ

WASM заменяет JavaScript? Нет. WASM решает задачи производительности; UI, fetch, DOM — на JS/TS.

Нужно ли учить Rust для WASM? Нет. AssemblyScript, C++ (Emscripten), Go — альтернативы. Rust — популярный выбор для новых модулей.

Можно ли отлаживать WASM как JS? Частично. Chrome DevTools поддерживает breakpoints в WASM; source maps связывают с исходниками Rust/C++.

WASM работает в Safari и Firefox? Да, во всех современных браузерах. Проверяйте edge features (threads, SIMD) отдельно.

Как передать JSON в WASM? Сериализуйте в UTF-8 байты в linear memory или парсите JSON на JS и передавайте поля как числа.

Node и браузер — один .wasm? Часто да, если не используете browser-only imports. Glue может отличаться: --target web для браузера и --target nodejs в wasm-pack для Node.

Blazor WASM или React? React/ecosystem шире для веб-UI; Blazor — если команда на .NET и нужен единый стек.

Безопасно ли запускать чужой WASM? Только из доверенных источников. Sandbox ограничивает систему, но не логические атаки (бесконечные циклы, memory exhaustion).

Что такое WASI? WebAssembly System Interface — API для файлов, часов, сокетов вне браузера (CLI, сервер).

Когда НЕ нужен WASM? CRUD, лендинги, простые калькуляторы — чистый JS быстрее разработать и поддерживать.


Web Workers и WASM

Вычисления на main thread блокируют отрисовку страницы. Web Worker — отдельный поток JavaScript без доступа к DOM; WASM загружают внутри worker.

worker.js

let wasmExports = null;

async function loadWasm() {
const res = await fetch('./add.wasm');
const { instance } = await WebAssembly.instantiateStreaming(res, {});
return instance.exports;
}

self.onmessage = async (e) => {
if (!wasmExports) wasmExports = await loadWasm();
const result = wasmExports.add(e.data.a, e.data.b);
self.postMessage({ result });
};

main.js

const w = new Worker('./worker.js', { type: 'module' });
w.onmessage = (e) => console.log('sum =', e.data.result);
w.postMessage({ a: 100, b: 23 });

Разбор:

  • Worker не видит document; доступны fetch, WebAssembly, postMessage.
  • Инициализация WASM один раз при первом сообщении.
  • Для SharedArrayBuffer и threads нужны заголовки COOP/COEP на сервере.

Пошаговый Emscripten (multiply)

git clone https://github.com/emscripten-core/emsdk.git ~/emsdk
cd ~/emsdk && ./emsdk install latest && ./emsdk activate latest
source ./emsdk_env.sh

multiply.c:

#include <emscripten.h>

EMSCRIPTEN_KEEPALIVE
int multiply(int a, int b) { return a * b; }
emcc multiply.c -o multiply.html \
-s EXPORTED_FUNCTIONS='["_multiply"]' \
-s EXPORTED_RUNTIME_METHODS='["cwrap"]'

Откройте через npx serve . — проверьте вызов из сгенерированного JS.


Отладка в Chrome DevTools

  1. Сборка с debug: wasm-pack build --dev.
  2. DevTools → Sources → WebAssembly → breakpoint.
  3. Performance → запись вызова fib(35) — сравните с JS flame chart.
  4. Memory — следите за ростом linear memory при утечках alloc.
Source maps в production

Не публикуйте maps на CDN без необходимости — они раскрывают структуру Rust-кода. Загружайте maps только в Sentry или staging.


ADR — шаблон решения "Вводим WASM"

## Контекст
Hot path X — 800ms в JS (DevTools, дата профиля).

## Решение
Модуль rust-x, граница wasm-bindgen, lazy import в Vite.

## Последствия
+ ожидаемый выигрыш на CPU-bound участке
- +45KB gzip к initial bundle
- rustup + wasm-pack в CI (620, 621)

Дополнительные упражнения

  1. Перенесите fib(40) в Dedicated Worker с WASM.
  2. Напишите WAT-функцию max(a,b) и экспортируйте рядом с add.
  3. Соберите Blazor WASM hello-world и замерьте cold start.
  4. Запустите тот же .wasm в Node через readFile + instantiate.
  5. Добавьте console_error_panic_hook в Rust и вызовите panic — проверьте вывод в консоли.

SIMD и bulk memory (обзор)

SIMD (Single Instruction Multiple Data) — параллельная обработка чисел в WASM. Проверяйте поддержку в caniuse.com. В Rust: std::arch + nightly или crates с fallback.

Bulk memory operations — быстрое копирование/заполнение linear memory. Ускоряет glue между JS и WASM.

Для большинства учебных проектов достаточно baseline WASM 1.0.


Интеграция с Express и WASM

import express from 'express';
import { readFile } from 'node:fs/promises';

const app = express();
let wasmAdd = null;

async function initWasm() {
const bytes = await readFile('./add.wasm');
const { instance } = await WebAssembly.instantiate(bytes);
wasmAdd = instance.exports.add;
}

app.get('/add', (req, res) => {
const a = Number(req.query.a);
const b = Number(req.query.b);
res.json({ result: wasmAdd(a, b) });
});

await initWasm();
app.listen(3000);

Паттерн: один раз загрузить WASM при старте сервера; запросы вызывают exports. Пакеты — 621, Node — 262.


Cloudflare Workers — WASM (концепт)

Workers принимают WASM как companion к JS. Ограничения:

  • лимит размера скрипта;
  • нет произвольной файловой системы;
  • API через bindings.

Следуйте актуальной документации Cloudflare перед production.


Сравнение glue-стеков

СтекЯзыкGlueТипичный размер
wasm-bindgenRustauto JS/TSсредний
EmscriptenC/C++embind/emscriptenбольшой
AssemblyScriptASgeneratedмалый
BlazorC#.NET runtimeочень большой
TinyGoGominimalмалый–средний

Дополнительный FAQ

Можно ли вызывать WASM из TypeScript strict mode? Да. Импортируйте .d.ts из wasm-pack; типы exports генерируются автоматически.

Нужен ли HTTPS для WASM? Нет для локальной разработки. Production — HTTPS стандарт; instantiateStreaming работает и на HTTP localhost.

Как тестировать WASM в Jest/Vitest? Загружайте .wasm через readFile в Node test environment; или mock exports для unit-тестов JS glue.


Упражнения

  1. Соберите add.wat вручную и вызовите из JS (практикум 1).
  2. Реализуйте multiply в WAT и добавьте второй export.
  3. Соберите Rust fib и сравните время с JS для n = 30, 35, 40.
  4. Подключите WASM-модуль в Vite с lazy import().
  5. Прогоните wasm-opt и сравните размер файла до и после.

Production и команда

ПрактикаЗачем
Версионировать .wasm в артефактах CIВоспроизводимые сборки
Source maps в stagingОтладка production-багов
Отдельный job wasm-pack buildНе ломать frontend CI
Документировать ABI (offsets, encoding)Контракт между JS и WASM
Лимит размера в bundle analyzerРегрессии размера

Связанные инструменты экосистемы:


Чек-лист перед production WASM

  • --release + wasm-opt применены
  • Lazy load или code splitting настроен
  • Fallback для браузеров без instantiateStreaming
  • Error boundary в JS вокруг init()
  • Метрики времени init() и первого call (RUM)
  • Source maps только на staging
  • CI job wasm-pack build зелёный
  • Документирован ABI между JS и WASM
  • Размер gzip в budget (< 100KB для mobile, пример)
  • Security review сторонних .wasm бинарников

Связанные материалы

ТемаМатериал
КомпиляцияЧто такое код — компиляция
RustRust — о разделе
JS runtimeNode.js — серверный JavaScript
C#C# — о разделе
ViteVite — сборка и dev-server
TypeScriptTypeScript — о разделе
Менеджеры версийnvm, pyenv, rustup
npm и lockПакетные менеджеры

Component Model и WASI — обзор

WebAssembly Component Model — следующий слой поверх базовых модулей: композиция модулей, типизированные интерфейсы между языками (WIT — WebAssembly Interface Types). В 2025–2026 активно развивается; в production чаще всё ещё классические .wasm + JS glue.

КонцепцияБазовый WASMComponent Model
ЕдиницаОдин модульКомпонент из модулей
Интерфейсыimport/export функцийWIT worlds
ЯзыкиRust + JS вручнуюГенерация bindings
СтатусПовсеместноEarly adopters

WASI (WebAssembly System Interface) — системные вызовы вне браузера: файлы, сockets (preview), clocks. Позволяет запускать WASM как wasmtime run app.wasm без Node.

# Пример с wasmtime (если установлен)
wasmtime run hello.wasm

Для браузера WASI не нужен — там хост предоставляет API через import.


Безопасность WASM — чек-лист

РискМитигация
Утечка памяти linear memoryЛимиты alloc, профилирование
Большой размер bundlelazy import, wasm-opt, code splitting
Panic в Rust → abortconsole_error_panic_hook в dev
Неверный ABI JS↔WASMДокументировать offsets, typed arrays
Source maps в prodТолько staging/Sentry
Непроверенный WASM из CDNSubresource Integrity, свой CI build

Sandbox WASM не защищает от логических уязвимостей (переполнение в вашем коде) — только от доступа к DOM/FS напрямую.


Бенчмarks — методология

Некорректные бенчмарки — главный источник мифов "WASM всегда быстрее JS".

Правила замера:

  1. Одна и та же машина, закрытые лишние вкладки.
  2. Chrome DevTools Performance — минимум 5 прогонов, медиана.
  3. Разделяйте cold start (download + compile) и steady state.
  4. Для I/O-bound задач WASM не поможет.
  5. Сравнивайте -O3 / --release с node --jitless off (default JIT).
ЗадачаJS (типично)WASM (типично)Вывод
fib(40) recursiveмедленнобыстрееCPU-bound OK
JSON.parse большойбыстро (native)медленнееНе дублировать
DOM updatesnativeнет доступаОставить JS
Image convolutionмедленнобыстрееКандидат
Crypto small payloadnative Web CryptoсравнимоЗависит от API

Интервью — типичные вопросы про WASM

ВопросКраткий ответ
WASM — язык?Нет, байт-код VM
Кто создаёт DOM?JavaScript, не WASM
Как передать строку?Linear memory + length, или wasm-bindgen
Rust обязателен?Нет; C++, Go, AssemblyScript
WASM в Node?WebAssembly.instantiate + Buffer
Когда не использовать?I/O, DOM, малый выигрыш vs размер bundle
SIMD в WASM?Да, для vector ops — проверять поддержку браузера

Blazor и C# в WASM

Blazor WebAssembly — UI на C#, компиляция в WASM, runtime .NET в браузере.

АспектДеталь
ПлюсыОдин язык для fullstack .NET команд
МинусыБольшой initial download, cold start
АльтернативаBlazor Server — UI на сервере, SignalR

См. C# intro, 5.04 .NET.

dotnet new blazorwasm -o BlazorApp
cd BlazorApp
dotnet run

Edge и serverless WASM

ПлатформаМодель
Cloudflare WorkersV8 isolates, WASM modules
Fastly ComputeWASM-first
Fermyon SpinWASM microservices
Docker + wasmtimeКонтейнеры с WASM OCI

Паттерн: компилируете Rust/Go → WASM → деплой на edge без полного Node runtime.


Roadmap изучения WASM (4 недели)

НеделяЦельМатериал
1WAT, load в браузереПрактикум 1 этой статьи
2Rust + wasm-bindgenRust intro
3Vite integration, lazy load288 Vite
4wasm-opt, CI, ADR620, 621

Дополнительные FAQ

Можно ли дебажить WASM как JavaScript?

Частично. Chrome DevTools поддерживает breakpoints в WASM при debug-сборке и source maps. Стек Rust читаемее с --dev и debug symbols.

Threading в WASM?

SharedArrayBuffer + atomics — требует COOP/COEP headers на странице. Без них — single-thread. Проверяйте политику безопасности сайта.

wasm-pack или cargo напрямую?

wasm-pack — обёртка для npm-публикации и шаблонов. Under the hood — wasm32-unknown-unknown target через rustup.



Содержание