Глубокие погружения

WebAssembly: что он решает и где не справляется

koboshiCo-founder
·7 мин чтения
WebAssembly: что он решает и где не справляется
Кратко

WebAssembly — не замена JavaScript. Это компактный бинарный формат инструкций, который позволяет браузерам выполнять код, скомпилированный из C, C++, Rust и других языков, со скоростью, близкой к нативной. В статье разбираются ограничения чистых веб-приложений, что решает WebAssembly, его реальные компромиссы, типичные сценарии использования и почему клиентская конвертация HEIC была бы невозможна без него.

Перетащите фото HEIC в браузерный конвертер. Сам файл — контейнер для данных изображения, закодированных HEVC: того же H.265, что используется для 4K-видео. В браузере нет встроенного декодера HEVC, а написать его с нуля на JavaScript было бы медленно, ненадёжно и громоздко. Реально нужный декодер — libheif, библиотека на C++, поддерживаемая strukturag. WebAssembly позволяет этому декодеру на C++ работать прямо в браузерной вкладке.

Именно этот пример раскрывает суть. WebAssembly — не новый язык программирования и не замена JavaScript. Это переносимый бинарный формат инструкций и изолированная среда выполнения, которая работает в браузере рядом с JavaScript.

Что такое WebAssembly на самом деле

WebAssembly (Wasm) — стандарт W3C. Он определяет компактный бинарный формат инструкций и стековую виртуальную машину. Обычно Wasm не пишут вручную: в него компилируют код на C, C++, Rust, Go, Zig, C# и всё большем числе других языков. Результат — модуль .wasm, который браузер скачивает, проверяет и выполняет в изолированной песочнице с безопасной памятью.

Все основные браузеры поддерживают WebAssembly с 2017 года. Формат модуля рассчитан на то, чтобы быть:

  • Компактным: бинарный формат разбирается быстрее, чем эквивалентный исходный JavaScript.
  • Быстрым: браузер компилирует его в машинный код заранее.
  • Безопасным: каждый модуль получает изолированную линейную память с проверкой границ.
  • Языконезависимым: любой язык, который может генерировать набор инструкций Wasm, может работать в вебе.

Ограничения классического веба

JavaScript — хороший язык для пользовательских интерфейсов, сетевых запросов и связующего кода. Он динамически типизирован, имеет сборку мусора и JIT-компиляцию. Эти свойства делают его гибким, но для тяжёлых вычислений — непредсказуемым.

Пауза сборки мусора может заморозить UI-поток посреди анимации. JIT-разогрев означает, что один и тот же код в разные моменты выполняется с разной скоростью. Для числовых и битовых операций — декодирования изображений, кодирования видео, криптографии, физического моделирования, больших матричных операций — JavaScript часто в десять раз медленнее той же логики, скомпилированной из C или Rust.

Другое ограничение — привязка к экосистеме. Десятилетиями накопленные библиотеки для работы с изображениями, аудио, видео и научные библиотеки написаны на C и C++. Переписать их на JavaScript — нереалистичный способ перенести эти возможности в веб.

Зачем появился WebAssembly

Wasm создавали, чтобы решить две проблемы сразу:

  1. Запускать существующий нативный код в браузере без переписывания на JavaScript.
  2. Давать веб-приложениям предсказуемый высокопроизводительный слой выполнения для задач, для которых JavaScript никогда не проектировался.

Wasm задуман как компаньон JavaScript, а не его преемник. DOM, сетевой стек и большинство API всё ещё принадлежат JavaScript. Wasm занимается изолированными вычислениями; JavaScript — оркестрацией.

Что решает WebAssembly

  • CPU-ёмкие задачи: декодирование изображений, перекодирование видео, физика, шифрование данных.
  • Предсказуемая производительность: нет сборщика мусора, нет кривой JIT-разогрева.
  • Повторное использование кода: перенос проверенных библиотек вроде libheif, FFmpeg, SQLite и OpenCV в браузер.
  • Приватность: конфиденциальные данные можно обрабатывать локально, а не загружать на сервер.
  • Офлайн-выполнение: после загрузки модуля .wasm он работает без сетевых запросов.

Плюсы и минусы

АспектПреимуществоОграничение
ПроизводительностьСкорость, близкая к нативной, для числовых задач и задач с интенсивным доступом к памятиНе быстрее нативной; всё ещё ограничена браузером и устройством
ПереносимостьОдин модуль работает в любом браузере и ОСДля DOM и большинства браузерных API нужен JavaScript-хост
БезопасностьИзолированная линейная память с проверкой границУязвим к побочным каналам вроде Spectre, как и любой браузерный код
ЭкосистемаПовторное использование существующих кодовых баз на C/C++/RustИнтероп с JavaScript добавляет сложность и накладные расходы
ЗапускБинарный формат быстро разбираетсяПервая загрузка и инициализация модуля могут быть ресурсоёмкими

Честный вывод: Wasm даёт браузеру возможность выполнять работу, которую раньше он не мог делать, но не снимает ограничений устройства пользователя.

Типичные сценарии использования

WebAssembly стал стандартным ответом, когда веб-приложению нужно выполнять тяжёлую работу локально:

  • Редактирование изображений и видео: Figma, Photopea и похожие инструменты используют Wasm для рендеринга и эффектов.
  • Перекодирование видео: FFmpeg.wasm запускает FFmpeg внутри браузера для конвертации форматов.
  • Оптическое распознавание символов: Tesseract.js портировал OCR-движок Tesseract на Wasm.
  • Игры: Unity, Godot и Unreal Engine могут экспортировать проекты в Wasm для браузерных игр.
  • Анализ данных: Pyodide переносит Python и научные пакеты; sql.js запускает SQLite в браузере.
  • Инференс моделей машинного обучения: ONNX Runtime Web использует Wasm-бэкенд для вычислений на CPU.
  • CAD и 3D-просмотрщики: сложные геометрические ядра, раньше бывшие только на десктопе.
  • Криптография: хеширование, шифрование и доказательства с нулевым разглашением, выполняемые на стороне клиента.

Распространённые библиотеки на базе WebAssembly

БиблиотекаОсноваЧто делает
heic-tolibheif через EmscriptenДекодирует изображения HEIC/HEIF и конвертирует в JPEG, PNG или битмап прямо в браузере.
FFmpeg.wasmFFmpeg через EmscriptenПерекодирование аудио/видео, ремультиплексирование и фильтрация полностью на стороне клиента.
Tesseract.jsTesseract OCR через EmscriptenРаспознаёт текст на изображениях в браузере.
sql.jsSQLite через EmscriptenЗапускает полноценный движок базы данных SQLite в браузере с файлом в памяти.
PyodideCPython через EmscriptenЗапускает Python и пакеты вроде NumPy, Pandas и SciPy без бэкенда.
ONNX Runtime WebONNX Runtime через EmscriptenВыполняет модели машинного обучения ONNX на CPU (Wasm) или GPU (WebGL/WebGPU).

За каждой строкой таблицы стоит один и тот же паттерн: взять зрелый нативный проект, скомпилировать его в Wasm и обернуть JavaScript API. В этом — практическая ценность WebAssembly.

Почему онлайн-конвертация HEIC в JPG/PNG/WebP нуждается в WebAssembly

HEIC — это контейнер, а не кодек. Сами данные изображения закодированы HEVC: это требует больших вычислительных ресурсов и связано с патентными ограничениями. Ни один браузер не поставляет нативный декодер HEVC, который могли бы использовать веб-страницы. Очевидный выход — серверная конвертация, но она требует загрузки фотографий пользователя.

Альтернатива — использовать тот же libheif, что и в десктопных инструментах, но скомпилированный в WebAssembly. Когда вы используете наш конвертер HEIC в JPG, декодирование происходит в вашем браузере:

  1. Файл проверяется чтением сигнатуры бокса ftyp.
  2. Wasm-модуль libheif декодирует HEVC-битстрим локально.
  3. Декодированный битмап записывается на canvas и экспортируется как JPEG.

Тот же модуль обеспечивает работу HEIC в PNG для вывода без потерь с прозрачностью и HEIC в WebP для оптимизированных под веб размеров. Никакой загрузки, никакой серверной обработки, никакая третья сторона не видит изображение.

Такой подход работает только потому, что WebAssembly позволяет запустить настоящий декодер изображений. Сам по себе JavaScript не справится с разбором HEVC за разумное время, а загрузка на сервер свела бы на нет обещание приватности. Именно Wasm делает это возможным.

Будущее WebAssembly

Wasm выходит за пределы браузера. WebAssembly System Interface (WASI) определяет переносимый системный интерфейс, который позволяет модулям Wasm работать на серверах, edge-воркерах и IoT-устройствах. Рантаймы вроде Wasmtime, Wasmer и WasmEdge уже используются в продакшене за пределами браузера.

Предложение Component Model позволит модулям Wasm предоставлять типизированные интерфейсы и компоноваться как библиотеки, упрощая подключение Rust-модуля к Python-хосту или Go-сервису. WebAssembly GC добавляет лучшую поддержку управляемых языков вроде Java и Kotlin. Всё это не про замену JavaScript в браузере — а про превращение Wasm в универсальную лёгкую целевую среду выполнения.

Внутри браузера тенденция та же: всё больше нативных возможностей уходит на сторону клиента, появляется больше инструментов, сохраняющих приватность, и всё больше библиотек, ранее бывших исключительно десктопными, теперь работают прямо во вкладке. WebAssembly — не та возможность, которую замечают пользователи, но именно он позволяет требовательным задачам работать в вебе.

Ещё посты в блоге