Пробуем делать web-frontend на Rust (WebAssembly)
Недавно вышла новость про то, что webassembly теперь включен в firefox 52 из коробки. А потом еще и chrome 57 подтянулся (правда, там вроде бы были какие-то баги с запуском). Я решил, что обязательно надо попробовать.
Для тех, кто не знает, что такое webassembly краткая информация: webassembly (или wasm) — это низкоуровневый язык, который понимают браузеры, и в который можно будет скомпилировать программы, написанные на популярных языках. Это гораздо более выгодно по скорости парсинга и выполнения, чем компилировать эти языки в чистый javascript или какой-нибудь asm.js.
Wasm задумывался в основном для c/c++, но, на удивление, уже все готово, чтобы скомпилировать программу на rust. Давайте сделаем небольшое приложение и посмотрим, что получится. Все это будем компилировать на Ubuntu. Без теоретических деталей, просто «пощупаем».
Устанавливаем Rust и emscripten SDK
Для начала нам понадобится rustup. Это инструмент для установки как самого rust компилятора, так и других вещей из rust мира.
curl https://sh.rustup.rs -sSf | sh
При установке в ваш ~.profile
будет прописан путь до бинарников cargo, но чтобы не перелогиниваться прямо сейчас, можно просто выполнить команду source $HOME/.cargo/env
.
Теперь нам надо добавить нужный target
rustup install stable
rustup default stable
rustup target add wasm32-unknown-emscripten
emscripten — это такой LLVM-to-javascript компилятор. Также умеет генерить и wasm. (Как известно, Rust использует llvm).
Надо скачать и распаковать sdk для этого дела. Качаем файл emsdk-portable.tar.gz
со страницы http://kripken.github.io/emscripten-site/docs/getting_started/downloads.html#sdk-downloads
Примерно так:
mkdir emsdk
cd emsdk
wget "https://s3.amazonaws.com/mozilla-games/emscripten/releases/emsdk-portable.tar.gz"
tar -xzf emsdk-portable.tar.gz
cd emsdk_portable
source emsdk_env.sh
Далее надо это дело скомпилировать. Предупреждаю, это может занять пару часов, причем с диким выжиранием процессора и памяти.
emsdk update
emsdk install sdk-incoming-64bit
emsdk activate sdk-incoming-64bit
emsdk предложит еще раз выполнитьsource ./emsdk_env.sh
Hello, world
Сделаем простенький хелловорлд на расте
fn main() {
println!("============\nHello, world\n===============");
}
И скомпилируем
rustc --target=wasm32-unknown-emscripten wasmtest.rs
Компилятор создаст файл wasmtest.wasm, а также js-обвязку для загрузки этого файла (wasmtest.js), потому что пока что нельзя просто взять и написать
Теперь нам надо сделать простую html-страницу для этого дела.
Rust Wasm
Чтобы посмотреть результат, проще всего запустить http-сервер на python, он не требует никакой конфигурации
python -m SimpleHTTPServer
Запустив в браузере (лучше в firefox) http://localhost:8000/hello.html
вы увидите в консоли надпись «Hello, world!».
Доступ к DOM
Консоль — это здорово, но хотелось бы что-то на странице отобразить, для этого нужны какие-то функции работы с DOM. Сначала я зарылся в мозгодробительную документацию, но потом выяснил, что всё уже написано до нас. Есть библиотека webplatform, которая предоставляет какие-то базовые вещи для работы с DOM.
Перепишем нашу программу:
extern crate webplatform;
fn main() {
println!("============\nHello, world\n===============");
let document = webplatform::init();
let body = document.element_query("body").unwrap();
body.html_set("Привет, Хабр, я web assembly!
");
let button = document.element_query("button").unwrap();
button.on("click", |_| webplatform::alert("Кнопка нажата!"));
}
Весь проект можете посмотреть на github
Собрать его можно так:
cargo build --target=wasm32-unknown-emscripten
rustc --target=wasm32-unknown-emscripten src/wasmtest.rs -L target/wasm32-unknown-emscripten/debug/deps/
(Я не особо знаток раста, так что если это можно сделать в одну команду cargo, подскажите плиз).
Потом запускаем наш питон-сервер
python -m SimpleHTTPServer
И смотрим в firefox http://localhost:8000/hello.html
. Должно получиться примерно так, как на КДПВ.
Скомпилированные файлы и hello.html тоже лежат в репозитории, так что вы можете просто пощупать результат у себя, не заморачиваясь с компиляцией.
Выводы и перспективы
Понятно, что сейчас всё сырое, неудобное и с багами, но у webassembly несомненно большое будущее. Всё, что требует сложных вычислений, можно будет перенести из javascript на wasm. Появятся тяжелые программы в вебе, о которых мы сейчас и мечтать не можем. Навороченные игры? Обработка видео и звука? Кто знает.
Куча библиотек на c, c++, rust и т.д. будет перенесена на веб в виде wasm-модулей.
Появились энтузиасты, которые хотят ускорить reactjs засчет rust и wasm (ссылка).
Появится закрытый проприетарный код. Если js, пропущенный через uglifyjs еще как-то можно читать, то c wasm это будет сделать гораздо сложнее.
Как всегда, добро пожаловать в коменты. Что думаете вы?
Комментарии (6)
28 марта 2017 в 11:18
0↑
↓
Ждём полноценные десктопные UI-фреймворки. Благо, они либо умеют рисоваться через OpenGL ES, либо можно на взять и отрендерить битмап из памяти.
28 марта 2017 в 11:46
0↑
↓
Другими словами, в 2018 мы будем запускать нативные десктопные приложения через браузер?
28 марта 2017 в 11:26
–2↑
↓
Ура рекламщики потирают руки от ощущения кучи денег.
Наконец будет неблокируемая исполняемая реклама.Появятся тяжелые программы в вебе, о которых мы сейчас и мечтать не можем
ага ядрёна вирусы,(загружающихся в память, во время исполнения- из за неведомого переполнения) зашифрующие диск (загрузочную область) за время нахождения на сайте при прокрутке какой нибуть 3 d картинки.
Появится закрытый проприетарный код.Если js, пропущенный через uglifyjs еще как-то можно читать, то c wasm это будет сделать гораздо сложнее
. А если сайт взломают негодяи и как такой код найти и разобрать?28 марта 2017 в 11:28
+1↑
↓
А вы пробовали сравнить скорость выполнения вставки куска ДОМа через wasm и обычными методами? Было бы интересно посмотреть быстродействие на реальных задачах, навроде обновления.28 марта 2017 в 11:38
0↑
↓
Глубоко не копал. Просто решил пощупать из любопытства.
28 марта 2017 в 11:41
0↑
↓
Немного размер получаемого wasm бинарника смущает, 183кБ.