WebAssembly в современной веб-разработке: за пределами JavaScript

Более двух десятилетий 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 — её важнейшее расширение за десятилетие. Разобраться в нём не факультативно для тех, кто хочет создавать приложения, раздвигающие границы возможного в вебе.

See what your own repository can account for.

Thirty minutes on a repository you choose, including the part the record cannot attribute.