Что такое WebAssembly
WebAssembly (wasm) — бинарный формат, который позволяет запускать код на различных платформах. Rust идеально подходит для wasm благодаря отсутствию GC и предсказуемому времени выполнения.
▸Преимущества Rust + WASM
Настройка окружения
1# Установка target2rustup target add wasm32-unknown-unknown34# Установка wasm-pack5cargo install wasm-pack67# Установка wasm-bindgen-cli8cargo install wasm-bindgen-cli
wasm-pack
▸Создание проекта
1# Создание нового проекта2cargo new --lib my-wasm-project3cd my-wasm-project
▸Cargo.toml
1[package]2name = "my-wasm-project"3version = "0.1.0"4edition = "2021"56[lib]7crate-type = ["cdylib", "rlib"]89[dependencies]10wasm-bindgen = "0.2"11js-sys = "0.3"1213[dependencies.web-sys]14version = "0.3"15features = [16 "Document",17 "Element",18 "HtmlElement",19 "Node",20 "Window",21]
▸Сборка
1# Dev сборка2wasm-pack build34# Release сборка5wasm-pack build --release67# С тестами8wasm-pack test --headless --chrome
wasm-bindgen
▸Экспорт функций
1use wasm_bindgen::prelude::*;23#[wasm_bindgen]4pub fn greet(name: &str) -> String {5 format!("Hello, {}!", name)6}78#[wasm_bindgen]9pub fn fibonacci(n: u32) -> u32 {10 match n {11 0 => 0,12 1 => 1,13 _ => fibonacci(n - 1) + fibonacci(n - 2),14 }15}
▸Импорт JavaScript
1use wasm_bindgen::prelude::*;23#[wasm_bindgen]4extern "C" {5 fn alert(s: &str);67 #[wasm_bindgen(js_namespace = console)]8 fn log(s: &str);9}1011#[wasm_bindgen]12pub fn show_alert(message: &str) {13 alert(message);14 log("Alert shown");15}
Web-Sys
▸DOM манипуляции
1use web_sys::{Document, Element, Window};2use wasm_bindgen::prelude::*;34#[wasm_bindgen(start)]5pub fn main() -> Result<(), JsValue> {6 let window = web_sys::window().expect("no global window");7 let document = window.document().expect("no document");89 let body = document.body().expect("no body");1011 let div = document.create_element("div")?;12 div.set_text_content(Some("Hello from Rust!"));13 div.set_attribute("class", "rust-component")?;1415 body.append_child(&div)?;1617 Ok(())18}
▸Обработка событий
1use web_sys::{Event, MouseEvent};2use wasm_bindgen::prelude::*;34#[wasm_bindgen]5pub fn setup_event_listener() -> Result<(), JsValue> {6 let window = web_sys::window().expect("no window");7 let document = window.document().expect("no document");89 let button = document.get_element_by_id("my-button")10 .expect("no button");1112 let callback = Closure::wrap(Box::new(move |event: MouseEvent| {13 web_sys::console::log_1(&"Button clicked!".into());14 }) as Box<dyn FnMut(MouseEvent)>);1516 button.add_event_listener_with_callback(17 "click",18 callback.as_ref().unchecked_ref()19 )?;2021 callback.forget();2223 Ok(())24}
Использование в JavaScript
▸HTML
1<!DOCTYPE html>2<html>3<head>4 <title>WASM Demo</title>5</head>6<body>7 <div id="output"></div>8 <script type="module">9 import init, { greet, fibonacci } from './pkg/my_wasm_project.js';1011 async function run() {12 await init();1314 const result = greet("World");15 document.getElementById('output').textContent = result;1617 const fib = fibonacci(10);18 console.log("Fibonacci(10):", fib);19 }2021 run();22 </script>23</body>24</html>
▸JavaScript
1import init, { greet, fibonacci } from './pkg/my_wasm_project.js';23async function main() {4 await init();56 console.log(greet("Alice"));7 console.log(fibonacci(20));8}910main();
Оптимизация
▸Уменьшение размера
1# Cargo.toml2[profile.release]3opt-level = "z" # Оптимизация по размеру4lto = true # Link-time optimization5codegen-units = 1 # Один codegen unit6strip = true # Удаление символов
▸wasm-opt
1# Установка wasm-opt2npm install -g wasm-opt34# Оптимизация5wasm-opt -Oz pkg/my_wasm_project_bg.wasm -o optimized.wasm
Тестирование
1#[cfg(test)]2mod tests {3 use super::*;45 #[test]6 fn test_greet() {7 assert_eq!(greet("World"), "Hello, World!");8 }910 #[test]11 fn test_fibonacci() {12 assert_eq!(fibonacci(0), 0);13 assert_eq!(fibonacci(1), 1);14 assert_eq!(fibonacci(10), 55);15 }16}
Реальные проекты
▸Игры на Rust + WASM
▸Вычислительно интенсивные задачи
Заключение
Rust и WebAssembly — мощное сочетание для создания высокопроизводительных веб-приложений. wasm-pack упрощает сборку, wasm-bindgen обеспечивает интеграцию с JavaScript. На собеседовании спрашивают про оптимизацию wasm, безопасность и типичные паттерны использования.