JavaScript процветает. Но благодаря WebAssembly его смерть может быть лишь вопросом времени.

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

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

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

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

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

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

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

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

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

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

Asm.js: ступенька

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

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

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

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

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

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

Если вам интересно, как выглядит WASM, представьте, что у вас есть такая функция 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. (Производительность пострадает. Пожалуйста, позвольте IE раствориться в безвестности!)

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

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

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

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

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. Веб-приложения не предназначались для замены настольных приложений. Но как только они смогли, они это сделали.

Если вы хотите следить за будущими историями, включая статьи о Blazor и Pyodide, подпишитесь на рассылку Young Coder.