Изучаем WebAssembly с помощью Rust


Внимание: с этой статьёй вы не освоите Rust, зато сможете быстро разобраться и приступить к работе с WASM, используя замечательный инструментарий wasm-pack и интуитивно понятную экосистему Rust.

Недавно я начал интересоваться Rust. Вы спросите: как я дошёл до жизни такой?

В какой-то момент вокруг WASM (Web Assembly) возникла шумиха, ажиотаж, и я вдруг почувствовал необходимость вплотную заняться чем-то новым… Движуха нарастала, и мне захотелось стать частью этой вечеринки ???? ???? ????.

Потихоньку я начал читать о wasm здесь и тут:

«WebAssembly — это новый тип кода, исполняемый в современных веб-браузерах. Он представляет собой низкоуровневый ассемблерный язык с компактным бинарным форматом, который работает с производительностью, близкой к нативной, и служит целью компиляции для таких языков, как C/C++ и Rust, позволяя им исполнять код в Сети.Он предназначен для дополнения JavaScript, позволяя им работать вместе».

Основное, что мы можем с WASM:

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

Пришёл за WASM, остался с Rust

Можно было бы запустить “hello world” или ещё какой-нибудь простенький пример, но мне хотелось поизучать другой язык (новую экосистему, новый мир!).

Изучение нового языка помогает лучше разбираться в основном языке, на котором работаешь: ты всё меньше обращаешь внимание на различия, всё больше замечаешь привычные шаблоны и оттого острее восприятие.

Мне пришлось выбирать между C/C++ и Rust. Недолго думая, я отдал предпочтение языку Rust. И у меня были на то свои причины:

  • Rust — это совершенно новый язык (новый и блестящий), в котором учтён опыт его старших собратьев для избежания «ошибок» экосистемы и использования лучших практик. (Я был реально заинтригован.)
  • Создали его замечательные ребята из Mozilla, которые хорошо поработали над документацией mdn (Mozilla Developer Network — сеть разработчиков Mozilla). Это сообщество, которое поддерживает интересные проекты с открытым исходным кодом, такие как a-frame, servo, mozillaThings и т.д.
  • У него классное название! На ум сразу же приходит альбом группы Megadeth “Rust in peace”(в переводе на русский «Ржавей с миром»).
  • Погуглив Rust, можно быстро обнаружить, что в его основе лежит парадигма «функционального» программирования, а его переменные совершенно неизменяемы по умолчанию (если не задействуется ключевое слово mut).
  • Заметил, что у него есть поддержка асинхронной среды выполнения, а я обожаю использовать неблокирующие функции, promises, async/await.
  • Кроме того, здесь есть хорошая система типов (на данный момент она не очень последовательна, зато есть дженерики).
  • Руководствовался я здесь скорее стремлением к большему удобству при написании кода, нежели какими-то соображениями, касающимися производительности или эффективности (безопасность доступа к памяти или небольшой размер двоичного кода, например). Просто мне нужен был язык, позволяющий писать в том стиле, который мне нравится (функциональный, но не только; с типами, с возможностями асинхронного программирования и т. д.).

    Изучаем Rust онлайн

    Есть хороший учебный курс Rust Fundamentals, посвящённый основам Rust, который можно смотреть на популярном онлайн-ресурсе pluralsight. Кроме того, я часто заглядываю в официальную документацию. Её составители потрудились на славу. Могу лишь пожелать вам проводить там столько же времени, сколько я посвящаю MDN. ????

    Настройка среды разработки

    Понадобится установить инструменты rust (компилятор, диспетчер пакетов, менеджер версий и т.д.). Следуйте инструкциям.

    ???? Примечание: Cargo — это как npm, rustup аналогичен nvm, а rustc — это компилятор, и я бы сказал, что он аналогичен tsc, но не могу: ведь он компилирует код не в другой высокоуровневый язык, а в бинарный код.

    И снова WASM — запускаем пилотную версию

    Очень хорошая документация (eng) поможет разобраться. Для быстрого запуска используйте краткое руководство (eng) по установке средств разработки Rust и WASM.

    При запуске проекта вам кое-что понадобится:

    • крейты — это сторонние зависимости, которые вы можете использовать (такие как npm portal repos);
    • cargo.toml — это как package.json. Узнайте, как его читать и редактировать, а также запускать его команды (новый, установить, публиковать и т.д.). Кстати, есть также автогенерируемый Cargo.lock;
    • крейты для Rust+WASM при разработке веб-приложения.

    Пилотную версию я запускал, следуя этому официальному справочному руководству, в котором описано применение инструмента под названием wasm-pack:

    wasm-pack— это универсальный механизм для создания, тестирования и публикации WebAssembly, сгенерированного с помощью Rust.

    Этот wasm-pack я и использовал при создании своего пилотного проекта. Можете заглянуть в мой репозиторий здесь и веб-демо.

    Давайте разберём самые интересные части проекта, чтобы понять, как всё это работает:

    Cargo.toml:

    • Крейт-зависимость web_sys — вот что нас интересует больше всего! Она даёт привязку ко всем API браузера (отражения кода механизма визуализации на C++, если я правильно понял то, что здесь написано).
    • Зависимость wasm-bindgen: с ней я имел дело при разработке приложения (библиотека Rust и инструмент CLI, облегчающие высокоуровневое взаимодействие между JavaScript и модулями wasm).

    lib.rs:

    #![allow(unused_variables)] fn main() { use wasm_bindgen::prelude::*; // Вызывается нашей точкой входа JS для запуска примера #[wasm_bindgen(start)] pub fn rust_in_peace() -> Result<(), JsValue> { // Используем глобальную функцию `окна` от `web_sys`, чтобы избавиться от глобального // объекта окна. let window = web_sys::window().expect("no global `window` exists"); let document = window.document().expect("should have a document on window"); let body = document.body().expect("document should have a body"); // Подготовим элемент, который мы будем добавлять let iframe = document.create_element("iframe")?; iframe.set_attribute("width", "560"); iframe.set_attribute("height", "315"); iframe.set_attribute("src", "https://www.youtube.com/embed/Mmbo4jQBKVU"); let h2 = document.create_element("h2")?; h2.set_inner_html("Rust In Peace made by Rust!"); body.append_child(&h2)?; body.append_child(&iframe)?; Ok(()) } }

    Обратили внимание на атрибут #[wasm_bindgen]? Благодаря ему будут созданы 2 обёртки:

    • обёртка JavaScript принимает типы JS и преобразует их в wasm;
    • обёртка Rust получает типы wasm и преобразует их в типы Rust.

    Больше узнать об этом можно в другой статье (eng).

    Шаблон wasm-pack

    Запуск сборщика модулей приведёт к созданию папок pkg и dist (файлу webpack config требуется @wasm-tool/wasm-pack-plugin, который компилирует наш ржавый код и генерирует pkg со всеми необходимыми шаблонами).

    Если мы откроем index.js, находящийся в папке pkg, то увидим следующее:

    import * as wasm from './index_bg.wasm'; /** */ export function rust_in_peace() { wasm.rust_in_peace(); }

    Wasm-pack сгенерировал обёртку JavaScript, которая вызывает нашу ржавую функцию, импортированную из бинарного кода WASM. Красота! ????

    Фронтенд-платформы на Rust для будущих проектов

    Существует множество проектов с открытым исходным кодом, которые охватывают практически все сферы, достаточно заглянуть в репозиторий awesome-rust.

    Если говорить о фронтенде, можно попробовать заняться разработкой «нативных» приложений на Rust (WASM) с использованием какой-нибудь платформы, чтобы работа шла быстрее/проще/более масштабно (с точки зрения кодовой базы и архитектуры программного обеспечения).

    Я предпочитаю Yew.Это современная платформа на Rust для создания внешней части (фронтенда) многопоточных веб-приложений с WebAssembly).

    На сегодня это всё. Если захотите использовать связку WASM+rust, наилучшим для вас инструментом будет wasm-pack, и документация у него отличная.


    Перевод статьи Liron Hazan: Intro to WebAssembly via Rust


    Поделиться статьей:


    Вернуться к статьям

    Комментарии

      Ничего не найдено.