Что такое WebAssembly и когда его использовать в браузере
Продвинутое3 минРедакция Innovialabs
Коротко
WebAssembly — компактный бинарный формат, который браузер выполняет почти с нативной скоростью рядом с JavaScript; он нужен для тяжелых вычислений и переноса готового кода, а не для обычных интерфейсов.
Коротко о WebAssembly
WebAssembly (Wasm) — это бинарный формат кода, который браузер выполняет в той же песочнице, что и JavaScript, но ближе к скорости нативных программ. Пишут его обычно не вручную: код на C, C++, Rust или другом языке компилируется в файл .wasm, который загружается на страницу.
Wasm не заменяет JavaScript. Он работает рядом с ним: JavaScript управляет страницей, DOM и событиями, а Wasm берет на себя тяжелые вычисления.
Как Wasm работает рядом с JavaScript
Схема взаимодействия:
- Браузер загружает модуль
.wasmи компилирует его. - JavaScript создает экземпляр модуля и получает доступ к его экспортированным функциям.
- Модуль может вызывать функции, которые ему передал JavaScript (импорты).
- Данные передаются через линейную память — общий буфер байтов, который видят обе стороны.
const { instance } = await WebAssembly.instantiateStreaming(
fetch("/math.wasm"),
{}
);
console.log(instance.exports.add(2, 3)); // 5
Важный нюанс: Wasm не имеет прямого доступа к DOM. Любая работа со страницей идет через JavaScript. Поэтому частые вызовы между JS и Wasm с маленькими порциями данных могут свести выгоду на нет — лучше передавать работу крупными блоками.
Какие языки компилируются в Wasm
| Язык | Инструменты | Особенности |
|---|---|---|
| Rust | wasm-pack, wasm-bindgen | Зрелая экосистема, удобная связка с JS, компактный результат |
| C / C++ | Emscripten | Позволяет переносить существующие библиотеки и движки |
| Go | Встроенная поддержка, TinyGo | Стандартная сборка тянет рантайм, TinyGo дает файлы меньше |
| AssemblyScript | Собственный компилятор | Синтаксис похож на TypeScript, проще старт для JS-разработчиков |
| C#, Kotlin и другие | Blazor, Kotlin/Wasm | Переносят свой рантайм, файлы обычно крупнее |
Языки со сборщиком мусора исторически тащили его в бандл. Поддержка GC на уровне самого Wasm это меняет, но проверяйте состояние для конкретного языка и браузеров.
Где Wasm действительно полезен
- Обработка изображений и видео: сжатие, конвертация форматов, фильтры прямо в браузере без отправки файла на сервер.
- Редакторы и сложные приложения: графические и CAD-редакторы, офисные инструменты, где важна скорость и уже есть большая кодовая база на C++ или Rust.
- Игры и 3D: движки, скомпилированные в Wasm, работают вместе с WebGL или WebGPU.
- Перенос существующих библиотек: базы данных, кодеки, парсеры, криптография — без переписывания на JavaScript.
- Вычисления на клиенте: симуляции, анализ данных, локальный запуск небольших ML-моделей.
Когда Wasm не нужен
- Обычные сайты, лендинги, формы, интернет-магазины — узкое место там в сети, изображениях и рендеринге, а не в скорости вычислений.
- Логика, которая в основном работает с DOM: вызовы через JavaScript съедят выигрыш.
- Небольшие задачи, где современный JavaScript-движок и так достаточно быстр.
Прежде чем выбирать Wasm, профилируйте: убедитесь, что проблема именно в вычислениях.
Ограничения
- Размер файлов: модуль с рантаймом языка может весить заметно больше эквивалентного JS.
- Отладка сложнее, хотя DevTools поддерживают source maps и DWARF для некоторых языков.
- Нет прямого доступа к DOM и большинству Web API — только через JavaScript-обертки.
- Многопоточность требует SharedArrayBuffer и специальных заголовков изоляции страницы.
- Безопасность: Wasm работает в песочнице, но уязвимости в исходном коде на C/C++ (например, переполнение буфера) могут повредить данные внутри памяти модуля.