På Webbfronten intet nytt: Första intryck av Rust och WebAssembly

Squeeds Julkalender | 2020-12-07 | Joel Hofgren
Några mer eller mindre sammanhängande personliga reflektioner och tankar kring Webassembly, vad det är, vad det kan användas till och vad det kanske betyda i framtiden. Allt baserat på en youtube-presentation, en till hälften genomläst bok och något hundratal rader Rust/HTML/Typescript.

Learn once, run everywhere

Som så många andra brukar jag hitta på små programmeringsprojekt som hobby.
Det kan handla om vad som helst egentligen, ibland är det en web app, ibland en jordfuktighetsmätare kopplad till en Raspberry Pi och ibland vill jag helt enkelt bara pröva något nytt språk eller teknik.
Det jobbigaste med detta är man hela tiden behöver byta programmeringsmiljö. För en server väljer jag Java, för front end behöver jag javascript, för raspberry blir det python. Och till dessa en uppsjö olika verktyg och konfigureringar!

För ett tag sen fick jag för mig att läsa av en temermometer/luftfuktighetsmätare med en Raspberry pi och skicka resultatet till lämplig databas. Vore ju kul att göra det i Java, tänkte jag, och kompilera till binär exekverbar fil med GraalVM.
Nej, det var inte kul. GraalVM kompilerar till samma arkitektur som host-maskinen, i mitt fall min laptop är en x86-64 maskin, men raspberry är Arm64-maskin. Raspberry:n vägrar exekvera mitt program. Så enkelt var det alltså inte. Jag måste bygga på en maskin med samma arkitektur som raspberry:n. Kanske kan Docker vara till hjälp? Jo, i princip ska det gå, men efter ett par frustrationsfyllda timmar gav jag upp.

Tänk vad skönt det hade varit om samma programmeringsmiljö hade gått att använda till allt, från front-end, server-side och embedded.

Så här här halvvägs in i boken "Programming WebAssembly With Rust" verkar det som att Rust kan erbjuda en lösning. Rust är ett modernt språk med ett flexibelt typsystem, pragmatisk inställning till funktionell programmering och garanterar minnessäker kod utan en garbage collector. Dessutom är det snabbt. Med byggverktyget Cargo gör det smidigt att kompilera till olika arkitekturer. En av de möjliga kompilerings målen är WebAssembly.

Vad är då det här WebAssembly?

Hemsidan ger följande definition:
WebAssembly (abbreviated Wasm) is a binary instruction format for a stack-based virtual machine. Wasm is designed as a portable compilation target for programming languages, enabling deployment on the web for client and server applications.Utöver det binära formatet finns också ett text-baserat format, "wat", avsett för människor. Så här kan en enkel "hello world" funktion som adderar två heltal se ut i en fil, add.wat:

(module
	(func $add (param $lhs i32) (param $rhs i32) (result i32)
		(i32.add 
			(get_local $lhs)
			(get_local $rhs)
		)
	)
	(export "add" (func $add))
)

och så här kan wat-filen kompileras till det binära wasm-formatet:

 $ wat2wasm add.wat -o add.wasm 

Och så här kan man använda modulen i en javascript-fil:

fetch('./add.wasm')
    .then(response => response.arrayBuffer())
    .then(bytes => WebAssembly.instantiate(bytes))
    .then(wasmModule => {
        console.log("1 + 1 = ", wasmModule.instance.exports.add(1, 1));
    })

Enkelt, eller hur? Kolla in webassembly.studio om du vill leka mer med handskriven WebAssembly.

För alla fall mer avancerade än "hello world" skriver man sin kod i ett annat högnivå språk och kompilerar sedan det till wasm.

Så, skriv kod i ett högnivå språk, kompilera till wasm ( en typ av bytekod), exekvera sedan bytekoden in en stackbaserad virtuell maskin. Som körs i browsern.

Hmm...visst låter det bekant? 

Har vi inte varit här förut, och visst gick det rätt kasst den gången? Nog påminner det hela väldigt mycket om Java, JVM och Java Applet programmeringsmodellen.
Själv har jag ganska varma minnen av Swing baserad Java Applet GUI-programmering från början av min karriär. Jag tyckte det var en ganska trevlig programmeringsmodell. Visst, det såg väl inte så fräckt ut alla gånger, men som utvecklare tyckte jag mycket om modellen. En modernare variant är Vaadin. Det är inget långt tankesteg att föreställa sig liknande modeller som drar nytta av wasm. Microsoft är tidigt ute här med sitt Blazor ramverk. Blazor kan ni för övrigt läsa mer om i en kommande lucka. Även Rust är med i matchen med t.ex Yew. Tänk bara, samma kod kan köras på servern som i klienten!

Jag kan se några saker som gör att WebAssembly kan ha större chans lyckas med detta jämfört med Java.
Även om Oracles försök att köra JVM i browsern till slut misslyckades så kan WebAssembly lära av misstagen som gjordes då. Det finns nu ett par årtionden av erfarenhet av att exekvera kod i en browser att bygga vidare på, och vilka svårigheter och problem som finns.

Det är från början ett open source projekt. Det betyder bland annat att det redan nu finns ett antal utvecklingsplattformar, jag nämnde några tidigare av de som redan finns ovan, jämfört med JVM som länge var låst till enbart Java.Idag är “transpilering” mellan olika språk vardagsmat, särskilt i javascript världen, och WebAssembly är designat för att vara portabelt.

Wasm moduler körs hostat i en sandlåda, de kan inte göra något som host:en inte tillåter den göra. Minne delas inte mellan moduler, nätverket är bara tillgängligt om host:en tillåter det, med mera.

Tar man ett steg tillbaka och begrundar allt detta så kanske man börjar se likheter mellan att köra främmande kod på sin egen laptop i en browser med att t.ex vara cloud-leverantör och låta andra ladda upp kod som körs i ditt datacenter. Eller en IoT-enhet som kan ta emot mjukvara trådlöst, en bil som får uppdateringar av sin självkörande programvara eller att ladda ner en app till sin mobiltelefon.
Utmaningarna är mycket likartade, även om det är helt olika användningsområden. Hur kan jag ha förtroende för koden som jag laddar ner över ett trådlöst nätverk? Hur kan jag minimera risken att skadlig kod kommer åt känslig information eller utför skadliga anrop? Är inte containerisering via t.ex Docker bara ett sätt att försöka isolera okänd applikationskod från underliggande operativsystem och andra applikationer?
Här tror jag att WebAssembly kan få stor betydelse i framtiden, och jag verkar inte vara ensam. Det är faktiskt fullt genomförbart att själv skriva en minimal wasm-host, vilket kan få stort genomslag i t.ex IoT/embedded världen. Eller varför inte ett hemmasnickrat "function-as-a-service" ramverk? Du publicerar ett enkelt API-kontrakt och allt dina användare behöver är att kompilera till wasm!

Hur det kommer att bli, det vet jag inte och några mer konkreta framtidsutsagor än så vågar jag mig inte på.

För den som kanske blivit lite nyfiken på att lära sig mer om WebAssembly så rekommenderar jag Kevin Hoffmans presentation och hans bok "Programming WebAssembly With Rust". För den som vill testa på Rust så tycker jag man ska passa på nu under Advent of code det är mycket bra sätt att bekanta sig med ett nytt språk. Mina egna trevande steg i Rust och WebAssembly hittar ni på min Github.

God Jul!