Это не требует больших усилий, и это может быть ключом к его распространению.

Я уже написал пару статей о WebAssembly и Rust, но этот пост должен быть полезен всем, кто пишет код на языке, который может компилироваться в WASM, особенно если вы используете первоклассные граждане WebAssembly, такие как Rust, C, С++ или Zig.

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

Рабочий процесс приложения WASM

Прежде чем перейти к тому, почему у вас должна быть версия вашего кода, совместимая с wasm, давайте посмотрим, как может выглядеть ваш процесс разработки и развертывания приложения WASM:

  1. написать код/перенести существующий код в форк, совместимый с wasm
  2. скомпилировать его в WebAssembly
  3. опубликовать двоичный файл .wasm
  4. попросите людей запустить его, например: wasmer run your_code.wasm

Вот и все: не требующее установки и кроссплатформенное (да, еще и мобильное) решение, которое требует только компиляции your_code в WebAssembly.

Это почти напоминает мне Docker, у них схожие характеристики, и, как объяснено здесь, докер может запускать контейнеры wasm, и они могут даже стать самым популярным контейнером.

Что значит компилировать в WASM

Создание кода, ориентированного на WebAssembly, означает, что любой может запустить его без установки, конфликтов зависимостей и строгой безопасности, особенно при написании кода на таких языках, как Rust, которые хорошо известны соблюдением правил безопасности во время компиляции.

Как пользователь, вам может быть удобнее запускать двоичный файл WASM, зная, что он работает в изолированной программной среде, пока виртуальная машина безопасна и не является, например, уязвимой для побега, если она не может проверить границы переменной, то есть, в данном случае проблема с переводчиком.

Даже если WASM является относительно новой технологией, такие сервисы, как Cloudflare, уже предоставляют среду для развертывания бессерверных функций Rust в сети Cloudflare, как если бы они были функциями JavaScript.

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

+1, если вы не полагаетесь на стандартную библиотеку Rust

std отлично подходит для большинства случаев использования, но сборки, ориентированные на WASM, с гораздо большей вероятностью будут работать в средах #[no_std], учитывая тот факт, что они могут быть встроенными системами или в общих средах, где каждый байт в двоичном файле .wasm имеет значение с точки зрения стоимость и производительность.

Стандартная библиотека Rust содержит множество вещей, поэтому, если вы можете создать свое приложение, опираясь на библиотеку core, это +1 для вас. Вам все еще может понадобиться использовать типы в std , например, векторы. Тем не менее, вместо того, чтобы использовать весь std и его прелюдию, вы можете создать свой собственный тип Vec или сделать свою собственную библиотеку std с базовыми типами, которые вам нужны.

Компиляция в WASM

Я работал только над WebAssembly с Rust, и я не думаю, что мне когда-нибудь понадобится переключаться на другой язык для этого. Если вы не знаете Rust/C/C++/Zig или любой другой язык с достойной поддержкой компиляции в WASM, вы можете использовать AssemblyScript (AS), но это, скорее всего, приведет к менее эффективному использованию памяти, что не обязательно означает что он будет работать намного медленнее, но в некоторых случаях, таких как разработка смарт-контрактов, вам нужно быть осторожным с тем, куда уходит ваша память, поскольку вы платите за нее в виде сборов, которые я всегда рекомендую использовать эффективные языки.

Этот раздел посвящен только компиляции Rust в WASM, поскольку у меня нет опыта компиляции с другими языками. Однако некоторые из этих советов могут быть полезны и для других языков, поскольку они относятся к более широкому двоичному коду WASM.

Скомпилировать вашу библиотеку в WebAssembly (на Rust) очень просто:

cargo build —-target wasm32-unknown-unknown

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

Несовместимость библиотек

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

  • Иногда вам просто нужно включить функции; некоторые библиотеки могут поддерживать WASM, но только с определенными флагами функций. В этом случае вы можете проверить файл Cargo.toml библиотеки и просмотреть доступные функции.
  • Откройте вопрос в репозитории библиотеки с вопросом о поддержке WASM, в лучшем случае мейнтейнер может его добавить.
  • Создайте форк библиотеки и добавьте поддержку WASM самостоятельно.
  • Используйте другую WASM-совместимую библиотеку

Избегайте файловой системы

В сети нет файловой системы. Таким образом, в WebAssembly его нет. Если вам нужно читать или записывать файлы, вы можете предоставить содержимое в качестве аргументов. Некоторые виртуальные машины также позволяют предоставлять входные и выходные данные в качестве аргументов CLI.

Кроме того, вы можете проверить WASI.

Избегайте системных библиотек

В WASM нет системных библиотек (очевидно), и крейт, привязанный к системной библиотеке, работать не будет.

Скептически относитесь к std-зависимым библиотекам

Библиотеки, использующие стандартную библиотеку Rust, с большей вероятностью будут выполнять незаконные операции wasm, такие как доступ к файловой системе.

Используйте wasm-bindgen, если вы общаетесь с JS

Здесь особо нечего сказать, wasm-bindgen — это мост между Rust и JavaScript. Если вы используете WASM в своем браузере, вам, вероятно, придется работать с этим ящиком. Например, Я использовал это в этой статье.

Не делайте синхронный ввод-вывод

Сеть асинхронна. Вы не можете синхронно выполнять ввод-вывод, но должны использовать фьючерсы. Например, вот как рабочему процессу Rust Cloudflare, который компилируется в WASM, удается дождаться содержимого полученного запроса:

router.post_async("/wasm", |mut req, ctx| async move {     
    ...
    let json_string = req.text().await?;
    ...
}

Вы можете видеть, как нам нужен асинхронный метод, который awaited дает результат.

Жалобы на распределитель

Если вы используете функции, которые выделяют память и хотите скомпилировать ее в wasm без стандартной библиотеки, вам нужно будет использовать wee_alloc в качестве объясняю в моем дополнительном блоге.

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

В зависимости от вашего кода его совместимость с WASM может иметь разные уровни сложности. В некоторых случаях это того не стоит, например, если код сильно зависит от файловой системы, и вы не собираетесь делать форк, работающий с WASI.

Эта статья не предназначена для того, чтобы сказать разработчикам, что всегда нужно писать WASM-совместимый код, а для того, чтобы рассмотреть некоторые политики, которые применяет веб-сборка, и подходят ли они для их приложений или инструментов. Несмотря на то, что я решительно выступаю за WebAssembly и пытаюсь мыслить в синтаксисе, совместимом с WASM, недавно я создал свой собственный статический блог, в котором для преобразования документов LaTeX в мои сообщения используется скрипт Rust, не совместимый с WASM. Как и во всем, все дело в компромиссах.

Спасибо за прочтение!