Более двух десятилетий JavaScript был бесспорным языком веба, но среда выполнения браузера уже не одноязычна. WebAssembly тихо стал второй средой выполнения в каждом современном браузере и открывает возможности, которые JavaScript в одиночку не даёт эффективно. Редакторы изображений, видеокодеки, движки баз данных, трёхмерные рендереры, среды выполнения языков — всё это сегодня работает во вкладках браузера, скомпилированное в низкоуровневый двоичный формат, который исполняется почти с нативной скоростью.
Что такое WebAssembly и почему это важно
WebAssembly — низкоуровневый двоичный формат инструкций, исполняемый стековой виртуальной машиной. Он задумывался как переносимая цель компиляции для языков программирования, позволяющая разворачивать в вебе и клиентские, и серверные приложения. Четыре производителя браузеров — Google, Mozilla, Apple и Microsoft — совместно работали над его проектом, и в 2019 году он стал стандартом W3C. Все крупные браузеры поддерживают его с 2017 года.
Но WebAssembly не замена JavaScript, а дополнение. JavaScript остаётся языком работы с DOM, обработки событий и логики интерфейса. WebAssembly берёт на себя вычислительно тяжёлую работу, для которой JavaScript никогда не предназначался. Обе среды сосуществуют в одной вкладке: модули импортируют функции JavaScript, а JavaScript вызывает экспорты Wasm через чётко определённый интерфейс.
WebAssembly не стремится заменить JavaScript. Он стремится решить задачи, которые JavaScript не решает эффективно. Веб-платформа от этого только выигрывает: разработчик может выбрать подходящий инструмент для каждой задачи внутри одного приложения.
Основы: двоичный формат и линейная память
Модули WebAssembly используют двоичный формат (файлы .wasm), рассчитанный на быстрый разбор и малый объём передачи. Формат компактен: типичный модуль заметно меньше эквивалентного JavaScript даже после минификации. Он кодирует типы, функции, импорты, экспорты, объявления памяти и инструкции в плотном представлении, которое браузер проверяет и компилирует за один линейный проход.
Любой модуль WebAssembly работает на концептуальной стековой машине. Инструкции кладут значения на стек вычислений и снимают их для выполнения операций. Поддерживаемые типы значений — i32, i64, f32 и f64: 32- и 64-битные целые и числа с плавающей точкой. На уровне Wasm нет ни строк, ни объектов, ни массивов, ни каких-либо других высокоуровневых типов. Любая сложная структура данных должна быть представлена в линейной памяти как сырые байты.
Линейная память — важнейшее понятие в WebAssembly. Каждый модуль может объявить один или несколько непрерывных блоков памяти с возможностью расширения. Эта память — плоский массив байтов, который модуль читает и пишет инструкциями загрузки и сохранения. Хост — среда выполнения JavaScript или Wasm — задаёт начальный и максимальный размер и может наращивать память, запрашивая дополнительные страницы по 65 536 байт каждая. Со стороны хоста эта память доступна как ArrayBuffer, то есть JavaScript читает и пишет ровно ту память, которой пользуется модуль.
Именно модель общей памяти делает WebAssembly эффективным. Хост и модуль обмениваются данными без сериализации и копирования — они просто пишут в один буфер. Когда функция на Rust возвращает строку в JavaScript, она записывает байты в линейную память и возвращает указатель (целочисленное смещение) и длину. JavaScript читает эти байты прямо из ArrayBuffer. Никакого разбора JSON, никакой передачи сообщений, никаких накладных расходов сверх самого вызова.
Строение модуля и проверка
Модуль WebAssembly состоит из секций: секция типов задаёт сигнатуры функций, секция функций объявляет их, секция кода содержит сам байт-код, секция памяти описывает линейную память, а секция экспортов делает функции и память доступными хосту. Перед исполнением браузер проверяет модуль структурно и обеспечивает типобезопасность. Проверка гарантирует, что все операнды соответствуют ожидаемым типам, все вызовы ссылаются на действительные сигнатуры, а все обращения к памяти остаются в объявленных границах. Это занимает миллисекунды и гарантирует, что искажённый модуль не сможет злоупотребить средой выполнения.
Модель безопасности явная и жёсткая. Модуль WebAssembly не может обратиться к DOM, сделать сетевой запрос, прочитать файл или как-либо взаимодействовать с системой, если хост явно не предоставил эти возможности через импортируемые функции. Модуль работает в песочнице, без доступа к чему-либо за пределами своей линейной памяти и таблицы импортируемых функций. Благодаря этому модули из недоверенных источников безопасно исполнять — свойство, критичное и в браузере, и на сервере.
Компиляция в Wasm: Rust, C, Go и Zig
Качество компиляции в WebAssembly сильно различается от языка к языку. Одни дают компактные, эффективные модули с минимальными накладными расходами. Другим нужна среда выполнения, добавляющая к двоичному файлу мегабайты. Выбор исходного языка зависит от ваших требований к производительности, опыта команды и нужной глубины интеграции.
Rust: золотой стандарт для Wasm
У Rust лучшая поддержка WebAssembly среди всех языков. Набор инструментов wasm-pack без трения берёт на себя компиляцию, оптимизацию и генерацию привязок к JavaScript. Rust даёт небольшие двоичные файлы, потому что у него нет сборщика мусора и тяжёлой среды выполнения, а модель владения естественно ложится на управление линейной памятью. Типичный модуль на Rust с несколькими экспортируемыми функциями после LTO и оптимизации занимает от 10 до 50 КБ — сопоставимо с Wasm, написанным вручную.
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
extern "C" {
fn alert(s: &str);
}
#[wasm_bindgen]
pub fn fibonacci(n: u32) -> u32 {
match n {
0 => 0,
1 => 1,
_ => fibonacci(n - 1) + fibonacci(n - 2),
}
}
#[wasm_bindgen]
pub fn greet(name: &str) -> String {
format!("Hello, {}! Wasm says hello.", name)
}Крейт wasm_bindgen порождает связующий код на JavaScript, который автоматически ведёт весь танец с линейной памятью. Вызов fibonacci из JavaScript выглядит и ощущается как любой другой вызов. Под капотом wasm_bindgen превращает строковые параметры в пары «указатель — длина», вызывает функцию Wasm и преобразует результат обратно в строку JavaScript. Этот слой абстракции стоит немного и делает связку Rust и Wasm пригодной для повседневной работы.
C и C++ через Emscripten
Emscripten — исходный набор инструментов для компиляции в Wasm. Он переводит код на C и C++ с помощью LLVM в качестве бэкенда и даёт обширный слой совместимости с POSIX, позволяющий переносить существующие нативные приложения в веб с минимальными правками исходников. Emscripten включает виртуальную файловую систему, трансляцию OpenGL в WebGL, эмуляцию pthread и среду выполнения на JavaScript, управляющую жизненным циклом модуля.
Go и официальный бэкенд Wasm
Go поддерживает WebAssembly с версии 1.11, и поддержка улучшается с каждым выпуском. Скомпилировать программу на Go в Wasm просто: задаёте GOOS=js GOARCH=wasm и запускаете go build. Однако у поддержки в Go есть заметные ограничения по сравнению с Rust. Go включает свою среду выполнения (планировщик горутин, сборщик мусора, стек defer) в каждый двоичный файл, поэтому минимальный модуль начинается примерно с 2 МБ. Для серверного Wasm это приемлемо, где размер значит меньше, но для браузера, где критичны время загрузки и разбора, — неприемлемо.
Zig: новый претендент
Zig позиционирует себя как современную замену C с первоклассной поддержкой WebAssembly. Его компилятор умеет целиться в Wasm напрямую, без обёрток вроде Emscripten. Zig даёт модули, сопоставимые с Rust по размеру и скорости, а возможность comptime позволяет метапрограммирование, полностью убирающее накладные расходы во время выполнения. Zig не тянет за собой скрытую среду выполнения — ни сборщика мусора, ни аллокатора, ни стартового кода, — если вы явно не подключите их сами.
- Rust даёт самые компактные двоичные файлы Wasm (10–50 КБ для типичных модулей) и лучшую экосистему инструментов — wasm-pack и wasm-bindgen.
- C и C++ через Emscripten — лучший выбор для переноса существующих нативных кодовых баз в Wasm: максимальная совместимость, но более крупные файлы.
- Go легко компилируется в Wasm, но из-за встроенной среды выполнения даёт большие файлы (свыше 2 МБ), поэтому подходит скорее для серверного Wasm.
- Zig даёт компактные модули без накладных расходов среды выполнения и идеален для минимальных встраиваемых сценариев.
Использование Wasm в браузере
Загрузка и запуск модуля WebAssembly в браузере следуют стандартному интерфейсу, одинаковому во всех современных браузерах. JavaScript-интерфейс предоставляет в пространстве имён WebAssembly функции compile, instantiate и instantiateStreaming. Потоковый вариант предпочтителен: он начинает компиляцию, пока байты ещё скачиваются, совмещая сетевой ввод-вывод с компиляцией.
async function loadWasm(url: string) {
const response = await fetch(url);
const results = await WebAssembly.instantiateStreaming(response);
return results.instance.exports;
}
async function main() {
const wasm = await loadWasm("/fibonacci.wasm");
console.log(wasm.fibonacci(40));
}
main().catch(console.error);instantiateStreaming возвращает объект со свойством instance (скомпилированный экземпляр модуля) и объектом exports, где собраны все функции и память, объявленные как экспорт. Вторым аргументом можно передать объект imports, дающий модулю доступ к тем функциям и значениям JavaScript, которые он ожидал при компиляции.
В продакшене модуль обычно компилируют заранее на этапе сборки или используют плагин сборщика. Webpack 5 поддерживает импорты Wasm нативно, у Vite поддержка экспериментальная. Эти сборщики сами берут на себя загрузку, создание экземпляра и жизненный цикл, позволяя импортировать модули Wasm как обычные модули JavaScript. С wasm-pack схема импорта выглядит как import init from './pkg/fibonacci.js' и даёт функцию инициализации на промисах, которая берёт на себя весь связующий код.
Критичный момент в браузере — первая компиляция. Модули переводятся из двоичного формата в нативный код при первой загрузке. Для маленьких модулей это единицы миллисекунд. Для больших — свыше 10 МБ — это могут быть сотни миллисекунд с блокировкой главного потока. Решение — использовать WebAssembly.compileStreaming в Web Worker: компиляция идёт вне главного потока и возвращает объект скомпилированного модуля, который главный поток создаёт мгновенно. Для приложений с крупными модулями этот приём обязателен.
WASI и серверный Wasm
WebAssembly изначально задумывался исключительно для браузера, но его модель безопасности и характеристики производительности делают его столь же привлекательным на сервере. Сложность в том, что браузер даёт особые интерфейсы хоста — DOM, fetch, WebSocket, — которых на сервере нет. WebAssembly System Interface решает это, определяя стандартный набор POSIX-подобных системных вызовов, доступных модулям вне браузера.
WASI предоставляет абстракции для файлового ввода-вывода, сети, доступа к часам, генерации случайных чисел, переменных окружения и аргументов командной строки. Модуль, собранный с поддержкой WASI, может читать файлы, открывать сетевые сокеты и взаимодействовать с операционной системой через стандартизованный интерфейс, работающий в любой совместимой среде. Это и есть основа для запуска Wasm в роли серверного приложения.
Стандарт WASI развивается через последовательные срезы. WASI preview 1 — стабильная база, которую сегодня поддерживает большинство наборов инструментов. WASI preview 2 вводит устройство, согласованное с моделью компонентов, и безопасность на основе возможностей, где каждый модуль явно объявляет, какие системные ресурсы ему нужны. Preview 2 — заметный архитектурный шаг вперёд: он делает возможными права мелкой гранулярности, когда модуль, которому нужно прочитать один конкретный файл, не может добраться ни до какого другого.
WASI превращает WebAssembly из браузерной технологии в универсальную изолированную среду выполнения. Один и тот же модуль, работающий во вкладке браузера, может работать и в серверной среде Wasm, и в бессерверной функции, и на пограничном узле — без изменений. «Напиши один раз, запускай где угодно» обретает новый смысл, когда это «где угодно» включает среды, куда JavaScript не добирается.
Среды выполнения Wasm и развёртывание
Запуск WebAssembly вне браузера требует серверной среды выполнения. Есть несколько зрелых вариантов с разными философиями и областями применения. Три главных — Wasmtime, Wasmer и WAMR (WebAssembly Micro Runtime) для встраиваемых систем.
Wasmtime
Wasmtime — самостоятельная среда выполнения от Bytecode Alliance, той же организации, что развивает стандарт WASI. Она написана на Rust, компилирует модули с помощью Cranelift (генератора кода, созданного специально для Wasm) и предоставляет интерфейсы для Rust, C, Python и других языков. Это самая распространённая среда для серверного Wasm; на ней работают Cloudflare Workers, Fastly Compute@Edge и другие платформы пограничных вычислений.
use wasmtime::*;
fn main() -> Result<()> {
let engine = Engine::default();
let module = Module::from_file(&engine, "hello.wasm")?;
let mut store = Store::new(&engine, ());
let instance = Instance::new(&mut store, &module, &[])?;
let hello = instance
.get_typed_func::<(), ()>(&mut store, "hello")?;
hello.call(&mut store, ())?;
Ok(())
}Интерфейс встраивания Wasmtime чист и идиоматичен. Вы создаёте Engine (среду компиляции), загружаете Module из файла или байтов, создаёте Store (контекст исполнения, хранящий линейную память Wasm) и создаёте экземпляр модуля, чтобы получить доступ к его экспортируемым функциям. Управление памятью, обработку ловушек и передачу системных вызовов WASI среда берёт на себя.
Wasmer
Wasmer — ещё одна популярная среда, поддерживающая несколько бэкендов компиляции: Cranelift, LLVM и Singlepass (быстрая JIT-компиляция с минимальной оптимизацией). Wasmer предлагает SDK для Rust, C, C++, Python, Go, PHP, Ruby, Java и других языков, что делает его доступным практически из любой среды программирования. Кроме того, у него есть реестр пакетов (WAPM) для распространения модулей Wasm — в духе npm.
Ключевая разница в том, что Wasmer делает ставку на удобство для разработчика и лёгкость встраивания, а Wasmtime — на соответствие стандарту и безопасность. Оба варианта отличны; выбор зависит от того, что вам важнее: широта экосистемы (Wasmer) или строгое следование спецификации и проверенная эксплуатация (Wasmtime).
- Wasmtime: лучший выбор для серверного Wasm в продакшене, строгое соответствие WASI, JIT-компилятор Cranelift, используется Cloudflare и Fastly.
- Wasmer: лучший выбор для встраивания Wasm в приложения не на Rust, поддерживает компиляцию через LLVM для почти нативной скорости, имеет экосистему пакетов WAPM.
- WAMR: лучший выбор для интернета вещей и встраиваемых устройств, крошечный размер, режимы интерпретатора и JIT, с утилитой командной строки iwasm.
Производительность: когда выигрывает Wasm
Выигрыш WebAssembly перед JavaScript зависит от характера нагрузки. Для операций, ограниченных процессором и насыщенных вычислениями, Wasm обычно быстрее в 1,5–3 раза. Для операций, интенсивных по памяти, вроде обработки изображений или сжатия, разрыв может быть больше, поскольку Wasm напрямую управляет раскладкой памяти и схемами выделения. Для нагрузок, где преобладают ввод-вывод или работа с DOM, преимущества нет, а из-за моста между модулем и хостом JavaScript могут появиться дополнительные издержки.
Играет роль и модель компиляции. JavaScript использует JIT: код начинает исполняться сразу, а горячие пути оптимизируются со временем. Wasm компилируется заранее или при загрузке модуля, поэтому выходит на пиковую скорость немедленно — периода прогрева нет. Для короткоживущих функций или однократных запусков это снимает задержку прогрева JIT, из-за которой JavaScript бывает медленнее при первом вызове.
По-настоящему Wasm выигрывает в предсказуемости. Оптимизация JIT в JavaScript недетерминирована: одна и та же функция может быть оптимизирована или деоптимизирована в зависимости от полученных типов, числа вызовов и состояния эвристик компилятора. Исполнение Wasm детерминировано. У каждой инструкции фиксированная цена. Нет пауз сборки мусора, нет путаницы типов, нет срыва оптимизаций. Поэтому Wasm — правильный выбор там, где ровность задержки важнее теоретического пика пропускной способности: обработка звука, физическое моделирование, финансовые расчёты.
- Wasm выигрывает в: обработке изображений и видео, синтезе и анализе звука, сжатии и распаковке данных, криптографических операциях, игровых движках, физических симуляциях, исполнении запросов к базе данных.
- JavaScript выигрывает в: работе с DOM, обработке событий, оркестрации сетевых запросов, отрисовке интерфейса через фреймворки, обработке строк и текста, небольших или редко вызываемых утилитах.
- Граница сдвигается: по мере того как Wasm получает доступ к веб-интерфейсам через WASI и модель компонентов, к нему переходит всё больше нагрузок, но JavaScript остаётся основным слоем интерфейса.
Модель компонентов и будущее Wasm
Модель компонентов WebAssembly — самое значимое развитие с момента первого выпуска. Она устраняет главное ограничение раннего Wasm: модули были изолированными хранилищами без стандартного способа стыковаться друг с другом. Модель компонентов вводит высокоуровневую, независимую от языка систему интерфейсов, позволяющую собирать модули как конструктор.
В нынешней модели модуль экспортирует функции, принимающие и возвращающие только целые числа и числа с плавающей точкой. Если модулю нужно передать другому строку, массив или сложную структуру, обоим приходится договариваться о соглашении по раскладке памяти: делить область линейной памяти и согласовывать выделение и освобождение. Это хрупко и зависит от языка. Модель компонентов решает это стандартизованной системой интерфейсных типов, которая обрабатывает строки, записи, варианты, списки и вложенные структуры через границы модулей.
Интерфейсные типы описывают данные, текущие между компонентами, независимо от языка. Компонент может экспортировать функцию, принимающую строку и возвращающую запись с двумя целочисленными полями, и любой другой компонент — написан ли он на Rust, C или Go — может её вызвать, ничего не зная о внутренней раскладке памяти соседа. Среда выполнения сама порождает логику адаптера и переводит между представлениями вызывающей и вызываемой стороны.
Примеры из практики
WebAssembly — не теоретическая технология. Он движет некоторые из самых требовательных веб-приложений в продакшене, и его распространение ускоряется по мере того, как инструменты взрослеют, а выигрыш в производительности становится неоспоримым.
Figma: первопроходец Wasm
Figma — самая известная история успеха. Её движок отрисовки написан на C++ и компилируется в Wasm через Emscripten. Figma переводит в один модуль Wasm всю кодовую базу на C++ — включая графическую библиотеку Skia, механизм формирования текста HarfBuzz и собственный движок раскладки. Слой JavaScript занимается событиями ввода и работой с DOM, а Wasm берёт на себя всю отрисовку, определение попаданий и расчёты раскладки. Итог — инструмент дизайна, который работает во вкладке браузера с производительностью, сравнимой с нативным настольным приложением.
SQLite: база данных в браузере
SQLite, вероятно, самый распространённый модуль Wasm в мире. Проект выпускает официальную сборку, которая запускает полный движок базы данных в браузере. Пользователь может выполнять запросы к базе полностью на стороне клиента, без серверной части. Сборка собирается через Emscripten и включает поддержку виртуальной файловой системы для сохранения баз в IndexedDB.
Последствия значительны. Приложения, которым нужны запросы на стороне клиента — инструменты анализа, панели отчётности, научные вычислительные блокноты — могут использовать SQLite в Wasm, чтобы выполнять сложные агрегации, соединения и оконные функции прямо в браузере, не отправляя данные на сервер. Библиотеки вроде sql.js и better-sqlite3-wasm оборачивают модуль в аккуратные интерфейсы JavaScript и делают его таким же удобным, как любой пакет npm.
Google Earth: Wasm для трёхмерной отрисовки
Google Earth для браузеров был перестроен на Wasm для обработки трёхмерного рельефа и конвейеров распаковки данных. Пока пользователь перемещается по карте, модуль получает сжатые двоичные данные, распаковывает их оптимизированными алгоритмами на C++, скомпилированными в Wasm, превращает геометрию в пригодные к отрисовке сетки и передаёт результат в WebGL — и всё это в пределах бюджета одного кадра анимации, без затрат на копирование данных.
- Figma использует Wasm для своего движка отрисовки на C++ и добивается почти нативной производительности при работе с векторной графикой в браузере.
- SQLite выпускает официальную сборку в Wasm, которая исполняет полный движок на стороне клиента и позволяет выполнять запросы офлайн без сервера.
- Google Earth опирается на Wasm для распаковки в реальном времени и обработки геометрии потоковых геоданных со скоростью 60 кадров в секунду.
- Adobe применяет Wasm в Photoshop для веба (код на C++, собранный Emscripten) для фильтров изображений и преобразований цветовых пространств.
- Zoom использует Wasm в веб-клиенте для декодирования видео и размытия фона.
Wasm на периферии и в бессерверных средах
Бессерверные платформы взяли WebAssembly как среду выполнения для пограничных вычислений из-за преимущества в холодном старте перед контейнерами. Модуль Wasm запускается за микросекунды, а не за миллисекунды, потому что не нужно загружать операционную систему, порождать процесс и инициализировать среду выполнения. Там, где задержка холодного старта напрямую влияет на восприятие продукта, это меняет всё.
Cloudflare Workers стала первой крупной платформой, принявшей Wasm. Workers работают в изолятах V8, способных исполнять и JavaScript, и модули Wasm. Worker, у которого вычислительная логика вынесена в модуль, начинает отвечать на запросы менее чем за 5 миллисекунд после холодного старта. Среда даёт ограниченный набор интерфейсов на основе спецификации Service Worker — fetch, Cache, хранилище KV и Durable Objects, — и модули с поддержкой WASI используют их через механизм импорта хоста.
Compute@Edge от Fastly использует Wasmtime как основную среду и требует, чтобы все вычисления компилировались в Wasm. Разработчики пишут логику на Rust, Go или JavaScript (который Fastly заранее компилирует в Wasm), и полученный модуль работает на пограничных узлах Fastly. Эта модель даёт прочную изоляцию — каждый запрос выполняется в свежем экземпляре без общего состояния — вместе со скоростью старта, которая делает пограничные вычисления практичными.
Экосистема Wasm на периферии ещё молода, но растёт быстро. Платформы вроде Fermyon Spin и Deislabs дают каркасы, созданные специально для бессерверных приложений на Wasm. Они скрывают детали среды WASI и предлагают привычные схемы — обработчики HTTP, хранилище «ключ — значение», задачи по расписанию, — исполняя всё через Wasm. Обещание в том, что бизнес-логику можно написать один раз на любом языке, компилируемом в Wasm, и развернуть без изменений на любой платформе, совместимой с WASI.
Как начать работать с Wasm сегодня
Лучший способ начать зависит от цели. Если Wasm нужен в браузере, самый быстрый путь — Rust с wasm-pack. Установите Rust, добавьте цель wasm32-unknown-unknown и создайте проект командой wasm-pack new. Сгенерированный проект содержит рабочий пример с функцией Wasm, вызываемой из JavaScript, скрипт сборки, выдающий совместимый с npm пакет, и тестовую обвязку, запускающую модуль в браузере без интерфейса.
Если хотите изучить серверный Wasm, начните с Wasmtime и его утилиты командной строки. Установите wasmtime, соберите любую программу на C или Rust с поддержкой WASI и запустите её командой wasmtime program.wasm. Вы увидите, что консольная программа, скомпилированная в Wasm, ведёт себя как нативный двоичный файл: читает со стандартного ввода, пишет в стандартный вывод, обращается к файлам и завершается с кодом состояния. Ощущения на удивление бесшовные.
Для экспериментов на периферии и в бессерверных средах Cloudflare Workers предлагает бесплатный уровень с поддержкой Wasm. Напишите функцию на Rust, скомпилируйте её в Wasm и разверните в глобальной сети Cloudflare. Вы увидите время отклика менее 10 миллисекунд из большинства точек мира и на собственном опыте убедитесь, что холодный старт с Wasm перестаёт быть проблемой.
Самый практичный первый шаг с Wasm — не переписывать всё приложение. Найдите одну вычислительно дорогую функцию — фильтр, преобразование, проверку, — перепишите её на Rust, скомпилируйте в Wasm и встройте в существующую кодовую базу. Измерьте разницу. Когда вы увидите трёхкратное ускорение на пятидесяти строках Wasm, вы поймёте, почему эта технология важна.
Инструментальный ландшафт быстро улучшается. wasm-pack, cargo-generate и wasm-tools дают зрелый рабочий процесс. Набор Binaryen предлагает wasm-opt для оптимизации модулей, сокращающий размер на 20–30 процентов. Wasmtime и Wasmer продолжают сокращать разрыв с нативным исполнением. А модель компонентов вскоре сделает модули совместимыми так, как было невозможно на старте Wasm.
WebAssembly не заменяет веб, каким мы его знаем. Он обогащает платформу — вторая среда выполнения, делающая то, чего не может JavaScript. В следующий раз, когда вы столкнётесь с проблемой производительности и почувствуете, что боретесь с динамической природой JavaScript, подумайте, нельзя ли вынести вычислительно тяжёлую часть в модуль Wasm. Инструменты готовы к продакшену, выигрыш реален, а будущее Wasm — с моделью компонентов, WASI preview 2 и более широкой поддержкой языков — только лучше.
Веб-платформа задумывалась расширяемой. WebAssembly — её важнейшее расширение за десятилетие. Разобраться в нём не факультативно для тех, кто хочет создавать приложения, раздвигающие границы возможного в вебе.