WebAssembly su Rust: naršyklės aplikacijų ateitis

Kodėl visi staiga kalba apie WebAssembly?

Jei pastaruoju metu sekate technologijų naujienas, tikriausiai pastebėjote, kad WebAssembly (arba sutrumpintai WASM) minimas vis dažniau. Ir ne be reikalo – tai technologija, kuri iš esmės keičia tai, kaip galvojame apie naršyklėse veikiančias aplikacijas. O kai sujungiate WebAssembly su Rust programavimo kalba, gaunate derinį, kuris daugeliui kūrėjų atrodo kaip tobula atsakymas į ilgametes web kūrimo problemas.

JavaScript dominavo naršyklėse daugiau nei du dešimtmečius. Tai nuostabi kalba, kuri leido internetui tapti tuo, kuo jis yra šiandien. Tačiau kai kuriose srityse JavaScript tiesiog nepakanka – kalbame apie sudėtingus skaičiavimus, vaizdo ar garso apdorojimą, žaidimų variklius ar bet kokias kitas užduotis, kurioms reikia maksimalaus našumo. Čia ir ateina WebAssembly su Rust.

WebAssembly nėra JavaScript pakaitalas – tai greičiau papildymas. Tai binarinis instrukcijų formatas, kurį naršyklės gali vykdyti beveik gimtojo kodo greičiu. O Rust? Tai sistema programavimo kalba, kuri garantuoja atminties saugumą be šiukšlių surinkimo mechanizmo ir siūlo našumą, prilygstantį C ar C++.

Rust ir WebAssembly simbiozė

Rust tapo viena populiariausių kalbų WebAssembly kūrimui ne atsitiktinai. Pirma, Rust kompiliatorius turi puikią WebAssembly palaikymą tiesiogiai integruotą. Antra, Rust filosofija – saugumas, našumas ir patikimumas – puikiai dera su tuo, ko reikia moderniam web kūrimui.

Vienas didžiausių Rust privalumų yra tai, kad kalba užkerta kelią daugeliui klaidų kompiliavimo metu. Jei jūsų kodas sukompiliuojasi, yra didelė tikimybė, kad jis veiks teisingai. Tai ypač svarbu, kai kuriate aplikacijas, kurios veiks milijonuose įrenginių su skirtingomis naršyklėmis ir operacinėmis sistemomis.

Dar vienas aspektas – Rust bendruomenė sukūrė puikų įrankių ekosistemą WebAssembly darbui. wasm-pack įrankis leidžia greitai sukurti, testuoti ir publikuoti WebAssembly paketus. wasm-bindgen biblioteka suteikia patogią sąsają tarp JavaScript ir Rust kodo. O web-sys ir js-sys crates suteikia prieigą prie visų Web API ir JavaScript funkcionalumo.

Praktinis pavyzdys: nuo nulio iki veikiančios aplikacijos

Geriausia teorija yra ta, kurią galima išbandyti praktiškai. Pažiūrėkime, kaip sukurti paprastą, bet veikiančią WebAssembly aplikaciją su Rust.

Pirmiausia jums reikės įdiegti Rust (per rustup.rs) ir wasm-pack įrankį. Tai užtrunka vos kelias minutes. Tada sukurkite naują projektą:

cargo new --lib mano-wasm-projektas
cd mano-wasm-projektas

Jūsų Cargo.toml faile reikia nurodyti, kad kuriate biblioteką, skirtą WebAssembly:

[lib]
crate-type = ["cdylib"]

[dependencies]
wasm-bindgen = "0.2"

Dabar pats įdomiausia dalis – kodas. Paprastas pavyzdys src/lib.rs faile:

use wasm_bindgen::prelude::*;

#[wasm_bindgen]
pub fn sveikink(vardas: &str) -> String {
format!("Labas, {}! Čia veikia Rust WebAssembly.", vardas)
}

#[wasm_bindgen]
pub fn skaiciuok_fibonacius(n: u32) -> u32 {
match n {
0 => 0,
1 => 1,
_ => skaiciuok_fibonacius(n - 1) + skaiciuok_fibonacius(n - 2)
}
}

Kompiliuojate su wasm-pack build --target web ir gaunate paruoštą WebAssembly modulį, kurį galite naudoti bet kurioje svetainėje. JavaScript kodas atrodytų maždaug taip:

import init, { sveikink, skaiciuok_fibonacius } from './pkg/mano_wasm_projektas.js';

async function run() {
await init();
console.log(sveikink("Jonas"));
console.log(skaiciuok_fibonacius(10));
}

Kur WebAssembly su Rust tikrai spindi

Teoriškai WebAssembly gali pakeisti JavaScript bet kurioje vietoje, bet praktiškai yra sritys, kur jis suteikia didžiausią naudą.

Vaizdo ir garso apdorojimas yra klasikinis pavyzdys. Įsivaizduokite foto redagavimo aplikaciją naršyklėje – filtrų taikymas, spalvų korekcija, dydžio keitimas. JavaScript gali tai padaryti, bet WebAssembly padarys 5-10 kartų greičiau. Figma, populiarus dizaino įrankis, naudoja WebAssembly būtent dėl šios priežasties.

Žaidimai yra kita akivaizdi sritis. Unity jau seniai palaiko WebAssembly eksportą. Bet su Rust galite kurti žaidimų variklius nuo nulio, naudodami tokius framework’us kaip Bevy ar Amethyst, ir kompiliuoti juos į WebAssembly.

Kriptografija ir saugumas – kai reikia atlikti sudėtingus kriptografinius skaičiavimus naršyklėje, Rust su WebAssembly yra idealus pasirinkimas. Rust garantuoja, kad jūsų kodas neturės atminties nutekėjimų ar kitų saugumo spragų, o WebAssembly užtikrina greitą vykdymą.

Duomenų analizė ir moksliniai skaičiavimai – jei kuriate įrankius, kurie apdoroja didelius duomenų kiekius tiesiogiai naršyklėje, WebAssembly leidžia tai daryti efektyviai. Kai kurios kompanijos jau perkelia Python duomenų analizės bibliotekas į WebAssembly.

Iššūkiai ir apribojimai, apie kuriuos reikia žinoti

Nors WebAssembly su Rust skamba kaip tobula technologija, ji nėra sidabrinė kulka. Yra keletas dalykų, kuriuos turėtumėte žinoti prieš šokdami į gilų vandenį.

Pirma, mokymosi kreivė yra gana stačia. Rust nėra lengva kalba pradedantiesiems. Jos savininko (ownership) sistema, skolinimosi (borrowing) taisyklės ir gyvavimo trukmės (lifetimes) gali sukelti galvos skausmą net patyrusiems programuotojams. Tačiau kartą įsisavinę šias koncepcijas, suprasite, kodėl jos egzistuoja ir kaip jos padeda rašyti geresnį kodą.

Antra, failo dydis gali būti problema. Net paprastas WebAssembly modulis su Rust gali būti 100-200 KB ar daugiau. Tai nėra problema greitam internetui, bet mobiliesiems įrenginiams su lėtu ryšiu gali būti iššūkis. Laimei, yra optimizavimo būdų – wasm-opt įrankis, tinkamas kompiliavimo konfigūracija ir kodo skaidymas gali žymiai sumažinti dydį.

Trečia, derinimas nėra toks paprastas kaip su JavaScript. Nors naršyklių kūrėjų įrankiai vis labiau palaiko WebAssembly, patirtis vis dar nėra tokia sklangi. Rust klaidos pranešimai yra puikūs, bet kai kažkas negerai veikia WebAssembly aplinkoje, gali prireikti papildomų pastangų problemai rasti.

Įrankiai ir bibliotekos, kurias verta išbandyti

Rust WebAssembly ekosistema sparčiai auga. Štai keletas įrankių ir bibliotekų, kurios gali žymiai palengvinti jūsų gyvenimą.

Yew – tai Rust framework’as, panašus į React. Jis leidžia kurti interaktyvias vartotojo sąsajas naudojant komponentų architektūrą. Jei esate įpratę prie React ar Vue, Yew jums atrodys pažįstamas, tik su Rust sintakse.

Trunk – puikus įrankis WebAssembly projektų kūrimui ir paleidimui. Jis automatiškai kompiliuoja jūsų Rust kodą, susieja su HTML ir CSS, ir net palaiko karštą perkrovimą (hot reload).

wasm-bindgen-futures – leidžia naudoti Rust async/await sintaksę su JavaScript Promise. Tai labai patogu, kai reikia dirbti su asinchroninėmis operacijomis.

console_error_panic_hook – maža, bet labai naudinga biblioteka, kuri Rust panikos pranešimus išveda į naršyklės konsolę. Be jos, kai jūsų kodas užstringa, matote tik bendrą klaidos pranešimą.

wee_alloc – mažas atminties skirstytojas, specialiai sukurtas WebAssembly. Jis gali sumažinti jūsų WASM failo dydį keliomis dešimtimis kilobaitų.

Našumo optimizavimas: kaip išspausti maksimumą

Vienas iš pagrindinių WebAssembly privalumų yra našumas, bet jį reikia mokėti išnaudoti. Štai keletas patarimų, kaip padaryti jūsų Rust WebAssembly kodą dar greitesnį.

Pirma, visada kompiliuokite su --release vėliava produkcijai. Skirtumas tarp debug ir release versijų gali būti 10x ar daugiau. Taip pat Cargo.toml faile galite pridėti papildomų optimizavimo nustatymų:

[profile.release]
opt-level = "z" # Optimizuoja dydžiui
lto = true # Link Time Optimization
codegen-units = 1

Antra, būkite atsargūs su duomenų perdavimu tarp JavaScript ir WebAssembly. Kiekvienas skambinimas per sieną (boundary) turi nedidelę pridėtinę kainą. Geriau perduoti didesnius duomenų blokus rečiau, nei mažus dažnai.

Trečia, naudokite wasm-opt įrankį iš Binaryen projekto. Jis gali dar labiau optimizuoti jūsų WebAssembly kodą po kompiliavimo:

wasm-opt -Oz -o output_optimized.wasm output.wasm

Ketvirta, jei jūsų aplikacija atlieka sunkius skaičiavimus, apsvarstykite galimybę naudoti Web Workers. Taip galite paleisti WebAssembly kodą atskirame gijoje ir išvengti pagrindinės gijos blokavimo.

Ateities perspektyvos ir kas laukia toliau

WebAssembly nėra statiškas standartas – jis nuolat tobulėja. Yra keletas būsimų funkcijų, kurios dar labiau išplės galimybes.

WASI (WebAssembly System Interface) leis WebAssembly moduliams veikti ne tik naršyklėse, bet ir serveriuose, IoT įrenginiuose ar bet kur kitur. Įsivaizduokite – rašote kodą vieną kartą Rust, ir jis veikia visur: naršyklėje, serveryje, edge computing platformose.

Gijos palaikymas (threads) jau yra eksperimentinėje stadijoje. Kai tai taps standartine funkcija, galėsime kurti tikrai galingas daugiagijės aplikacijas naršyklėse.

Garbage Collection palaikymas leis lengviau integruoti kitas kalbas su WebAssembly. Nors Rust neturi šiukšlių surinkimo, kitos kalbos kaip Java, C# ar Python galės efektyviau veikti WebAssembly aplinkoje.

Component Model – tai būsimas standartas, kuris leis kurti modulinius, lengvai pakartotinai naudojamus WebAssembly komponentus. Tai bus tarsi npm ekosistema, bet WebAssembly pasaulyje.

Rust bendruomenė taip pat neatsilieka. Nauji framework’ai ir bibliotekos atsiranda kas mėnesį. Egui – nedidelis GUI framework’as, kuris veikia ir naršyklėje, ir kaip native aplikacija. Leptos – naujas web framework’as, kuris žada būti greitesnis už Yew. Dioxus – dar vienas įdomus projektas, leidžiantis kurti cross-platform aplikacijas.

Ar verta šokti į WebAssembly su Rust dabar?

Atsakymas priklauso nuo jūsų situacijos. Jei kuriate įprastą svetainę ar paprastą web aplikaciją, JavaScript su moderniu framework’u (React, Vue, Svelte) vis dar yra geresnis pasirinkimas. Jis paprastesnis, turi didesnę bendruomenę ir daugiau paruoštų sprendimų.

Bet jei jūsų projektas reikalauja didelio našumo, jei dirbate su sudėtingais algoritmais, vaizdo ar garso apdorojimu, arba jei tiesiog norite išmokti kažko naujo ir perspektyvaus – WebAssembly su Rust yra puikus pasirinkimas. Technologija jau yra pakankamai brandi produkciniam naudojimui, o jos ateitis atrodo labai šviesi.

Pradėti nėra taip sunku, kaip gali atrodyti. Rust dokumentacija yra puiki, bendruomenė draugiška, o WebAssembly įrankiai tampa vis geresni. Taip, mokymosi kreivė yra stačioka, bet įgūdžiai, kuriuos įgysite, bus vertingi ne tik web kūrimui, bet ir sistemų programavimui apskritai.

Galiausiai, net jei neketinate naudoti WebAssembly savo kasdieniniame darbe, supratimas, kaip jis veikia ir ką gali, padės jums tapti geresniu programuotoju. Tai technologija, kuri keičia tai, ką galime pasiekti naršyklėse, ir būti jos dalimi dabar reiškia būti priekyje to, kas taps įprasta po kelių metų.

Daugiau

Pico CSS: minimalistinis framework