Десять лет назад никто не догадывался о том, что JavaScript будет править миром. Другие платформы, такие как Java, Flash и Silverlight, также были сильными противниками. Все трое нуждались в плагине для браузера, чтобы выполнять работу, и заменяли HTML другим подходом к пользовательскому интерфейсу. Благодаря этому подходу они смогли значительно опередить JavaScript с такими функциями, как возможность добавить видео, анимацию и график, задолго до появления элемента <video>, спецификации CSS Animations и HTML canvas. Но это также стало причиной их падения. После взрыва мобильного браузинга и принятия HTML эти платформы устарели.

В то же время JavaScript завоевывал мир, посеяв крошечное семя, которое, возможно, станет его концом в будущем. Этим семенем была экспериментальная технология под названием asm.js.

Но прежде чем перейти к этой теме, сделаем шаг назад и рассмотрим ситуацию на сегодняшний день.

Транспайлинг: текущий подход

Во все времена существования JavaScript разработчики пытались найти альтернативные подходы. Одним из первых было использование плагинов для извлечения кода из браузера (и он потерпел неудачу). Другая идея заключалась в том, чтобы создать инструменты разработки для конвертирования кода. Другими словами, взять код, написанный на другом более уважаемом языке, и преобразовать его в JavaScript.

Процесс преобразования одного языка в другой называется транспайлингом, и у него есть некоторые очевидные недостатки. Высокоуровневые языки обладают различными функциями, синтаксисом и идиомами, которым не всегда можно найти эквивалентные конструкции в другом. И даже если они есть, то опасность поджидает на каждом углу. Что произойдет, если сообщество остановит разработку транспайлера? Или если транспайлер станет причиной возникновения ошибок? Или при необходимости подключить фреймворк JavaScript, например, к Angular, React или Vue? И каким образом работать в одной команде, если все говорят на разных языках?

Как и во многих случаях в программировании, преимущества инструмента зависят от сообщества, работающего над ним.

На данный момент транспайлеры достаточно распространены, но используются только для обеспечения обратной совместимости.

Разработчики пишут самый современный JavaScript, а затем используют такие транспайлеры, как Babel, для преобразования в эквивалентный (но менее элегантный) код JavaScript старой закалки, работающий везде. Или они используют TypeScript (модернизированный вариант JavaScript с такими функциями, как строгая типизация, обобщенные и ненулевые типы), а затем переносят его в JavaScript. В любом случае, мы все еще играем в «огражденном саду» JavaScript.

Asm.js: шаг вперед

Первый источник новых возможностей предоставил asm.js — необычный эксперимент от разработчиков Mozilla 2013 года. Они искали способ запуска высокопроизводительного кода внутри браузера. Но в отличие от плагинов, asm.js не пытался идти по одному пути с браузером. Вместо этого он прокладывал туннель прямо через виртуальную машину JavaScript.

asm.js — это краткий оптимизированный синтаксис JavaScript. Он работает быстрее, чем обычный JavaScript, обходя медленные динамические части языка. Веб-браузеры, которые распознают это, также применяют другие оптимизации, значительно повышая производительность. Другими словами, asm.js следует золотому правилу — не ломайте веб — предлагая путь к будущим улучшениям. Команда Firefox использовала asm.js вместе с инструментом транспайлинга Emscripten для размещения 3D-игр реального времени, разработанных на C++, в веб-браузер, работающий только на JavaScript и сырых амбициях.

Движок Unreal, работающий на asm.js

Asm.js заставил разработчиков переосмыслить роль JavaScript. Код Asm.js — это тот же JavaScript, но он не предназначен для чтения или написания вручную, а создается с помощью автоматизированного процесса (транспайлера) и передается прямо в браузер.

WebAssembly: новая технология

Хотя с помощью эксперимента asm.js было создано несколько хороших демонстраций, он не особо заинтересовал разработчиков. Однако все изменилось с появлением WebAssembly.

WebAssembly является как преемником asm.js, так и абсолютно другой технологией. Он представляет собой компактный двоичный формат для кода. Как и asm.js, код WebAssembly направляется в среду выполнения JavaScript. Он получает ту же песочницу и среду выполнения. Также как asm.js, WebAssembly компилируется таким образом, чтобы обеспечить дальнейшую эффективность, которая стала еще более впечатляющей. Теперь браузер может пропускать этап синтаксического анализа JavaScript. При наличии обычной логики (например, трудоемких вычислений) WebAssembly работает намного быстрее, чем обычный JavaScript, и почти так же быстро, как нативно скомпилированный код.

Упрощенный взгляд на конвейер обработки WebAssembly

Представьте, что у вас есть подобная функция C:

int factorial(int n) {
  if (n == 0)
    return 1;
  else
    return n * factorial(n-1);
}

Она скомпилируется в код WASM, который выглядит следующим образом:

get_local 0
i64.eqz
if (result i64)
    i64.const 1
else
    get_local 0
    get_local 0
    i64.const 1
    i64.sub
    call 0
    i64.mul
end

При передаче по проводам код WASM преобразуется в двоичный код.

WebAssembly предназначен для использования компилятором. Его не нужно писать вручную (но можно, если вы хотите изучить его более подробно).

WebAssembly появился в 2015 году. Теперь он полностью поддерживается четырьмя большими браузерами (Chrome, Edge, Safari и Firefox) на настольных и мобильных устройствах. Он не поддерживается в Internet Explorer, хотя обратная совместимость возможна путем преобразования кода WebAssembly в asm.js (но производительность пострадает).

WebAssembly и будущее веб-разработки

«Из коробки» WebAssembly предоставляет разработчикам способ написания оптимизированных стандартных процедур, обычно на C++. Это мощная способность, но с относительно узкой сферой применения. Она используется для улучшения производительности сложных вычислений (например, fastq.bio использовал WebAssembly для ускорения расчетов секвенирования ДНК.) Она также применяется при портировании высокопроизводительных игр или написании эмулятора, работающего внутри браузера. Если бы это были все сферы применения WebAssembly, то у него не было бы шансов вытеснить JavaScript. Но WebAssembly также открывает путь для разработчиков фреймворков, предоставляя возможность переместить платформы в среду JavaScript.

Здесь ситуация принимает интересный оборот. WebAssembly не может обойти JavaScript, поскольку он заперт в его среде выполнения. Он должен работать параллельно хотя бы с некоторым количеством обычного кода JavaScript из-за отсутствия прямого доступа к странице. Это означает, что он не может манипулировать DOM или получать события, не пройдя через слой JavaScript.

Звучит как значительное ограничение, однако разработчики нашли способ перенаправить среды выполнения через WebAssembly. Например, фреймворк Blazor от Microsoft загружает небольшую среду выполнения .NET в виде скомпилированного файла WASM. Эта среда работает с JavaScript и предоставляет базовые сервисы (такие как сборка мусора) и функции высшего уровня (слои, маршрутизация и виджеты пользовательского интерфейса). Другими словами, Blazor использует виртуальную машину, которая находится внутри другой виртуальной машины.

Blazor — это не единственный эксперимент на основе WebAssembly. Например, Pyodide, который размещает Python в браузере вместе с расширенным математическим инструментарием для анализа данных.

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

WebAssembly стремительно продолжает свое развитие. Его текущая реализация — лишь минимально жизнеспособный продукт, достаточный для использования в некоторых важных сценариях, но не универсальный во всей веб-разработке. Как только WebAssembly будет утвержден, ситуация улучшится. Например, если такие платформы, как Blazor, завоюют популярность, WebAssembly, вероятно, добавит поддержку прямого доступа к DOM. Создатели браузеров уже планируют добавить сборщик мусора и многопоточность, чтобы средам выполнения не нужно было реализовывать эти детали.

Если этот путь эволюции кажется долгим и сомнительным, то вспомните о JavaScript. Из начала мы поняли, что если что-то возможно в JavaScript, то это можно выполнить. Затем мы узнали, что если действие повторяется достаточно часто, то браузеры улучшают его работу. И так далее. Если WebAssembly станет популярным, то он внесет свой вклад в эффективный цикл улучшений и сможет с легкостью превзойти нативные преимущества JavaScript.

Часто говорят, что WebAssembly не был создан для замены JavaScript. Но так можно сказать о любой революционной платформе. JavaScript не был разработан для замены встроенного в браузер Java, а веб-приложения не были предназначены для замены настольных приложений. Но при первой же возможности они это сделали.

Читайте также:


Перевод статьи Matthew MacDonald: What Replaces JavaScript

Предыдущая статьяКак создавать веб-сокеты в Python
Следующая статьяПочему мы создаем инфраструктуру машинного обучения в Go, а не в Python