I denne fjerde delen av vår introduksjon til WebAssembly, skal vi se nærmere på samspillet mellom WebAssembly og JavaScript.
Her vil du lære hvordan du kan benytte WebAssembly sammen med JavaScript, og vi skal også utforske WebAssembly JavaScript API.
WebAssembly er en åpen standard i binær form som muliggjør utvikling av applikasjoner med ytelse som native applikasjoner direkte i nettlesere. Hvis du ikke har lest de foregående delene i denne veiledningen, anbefaler vi at du gjør det.
La oss begynne.
Samarbeid mellom WebAssembly og JavaScript
I første del av denne WebAssembly-serien diskuterte vi hvordan WASM fungerer. For å skape høyytelseskode for din webapplikasjon, må du benytte WASM API-er og funksjonalitet i JavaScript. Vi snakket også om hvordan JavaScript-rammeverk kan utnytte WASM for å utvikle applikasjoner med høy ytelse.
Det er imidlertid ikke mulig å laste inn WASM-moduler som ES6-moduler ved bruk av <script type="module">
. Her kommer JavaScript inn i bildet. Det bistår med å laste og kompilere WASM i nettleseren. Prosessen er som følger:
- Last inn .wasm-bytene i en ArrayBuffer eller en typet array.
- Bruk WebAssembly.Module for å kompilere bytene.
- Du kan nå instansiere WebAssembly.Module med import for å få tilgang til eksporterte funksjoner.
Du trenger altså en forhåndskompilert WASM-modul. Her finnes det flere valgmuligheter. Du kan bruke Rust, C/C++, AssemblyScript eller til og med TinyGo (Go) for å skrive koden og deretter konvertere den til en .wasm-modul.
WebAssembly fungerer som et mål for samling for forskjellige programmeringsspråk. Dette innebærer at du må skrive koden i det språket du foretrekker, og deretter bruke den genererte binærkoden i applikasjonen din (enten det er webbasert eller ikke). Hvis du skal bruke det på servere, er det nødvendig å benytte WASI for å kommunisere med systemene.
Siden WebAssembly bruker lineært minne via en utvidbar matrise, kan både JavaScript og WASM få synkron tilgang til dette, noe som gir deg muligheten til å utvikle funksjonsrike og raske applikasjoner.
Eksempler på integrasjon av WebAssembly og JavaScript
La oss se på noen praktiske eksempler for å lære hvordan man bruker WASM med JavaScript.
Som nevnt tidligere, trenger du en forhåndskompilert WASM-modul. I dette eksemplet bruker vi Emscripten (C/C++). Ettersom WASM tilbyr et binært format med høy ytelse, kan vi kjøre den genererte koden sammen med JavaScript eller andre språk.
Oppsett av verktøy
Ettersom vi benytter Emscripten, trenger vi emsdk-verktøyet. Dette verktøyet gjør det mulig å kompilere C/C++-kode til .wasm-kode.
Bare kjør følgende kommando i din terminal. Hvis du ikke har GIT installert, kan du følge vår guide «Open Source 101: Versjonskontrollsystem og Git» for å installere det.
git clone https://github.com/emscripten-core/emsdk.git cd emsdk
#Output [email protected]:~/Projects/WASM2$ git clone https://github.com/emscripten-core/emsdk.git Cloning into 'emsdk'... remote: Enumerating objects: 3566, done. remote: Counting objects: 100% (62/62), done. remote: Compressing objects: 100% (49/49), done. remote: Total 3566 (delta 31), reused 38 (delta 13), pack-reused 3504 Receiving objects: 100% (3566/3566), 2.09 MiB | 2.24 MiB/s, done. Resolving deltas: 100% (2334/2334), done. [email protected]:~/Projects/WASM2$ cd emsdk [email protected]:~/Projects/WASM2/emsdk$
I emdsk-mappen kjører vi en ny kommando for å laste ned den nyeste ferdige Emscripten-byggingen.
Dette gjør du med følgende kommandoer.
./emsdk install latest ./emsdk activate latest source ./emsdk_env.sh
#Output [email protected]:~/Projects/WASM2/emsdk$ ./emsdk install latest Resolving SDK alias 'latest' to '3.1.31' Resolving SDK version '3.1.31' to 'sdk-releases-1eec24930cb2f56f6d9cd10ffcb031e27ea4157a-64bit' Installing SDK 'sdk-releases-1eec24930cb2f56f6d9cd10ffcb031e27ea4157a-64bit'.. Installing tool 'node-14.18.2-64bit'.. Downloading: /home/nitt/Projects/WASM2/emsdk/zips/node-v14.18.2-linux-x64.tar.xz from https://storage.googleapis.com/webassembly/emscripten-releases-builds/deps/node-v14.18.2-linux-x64.tar.xz, 21848416 Bytes Unpacking '/home/nitt/Projects/WASM2/emsdk/zips/node-v14.18.2-linux-x64.tar.xz' to '/home/nitt/Projects/WASM2/emsdk/node/14.18.2_64bit' Done installing tool 'node-14.18.2-64bit'. Installing tool 'releases-1eec24930cb2f56f6d9cd10ffcb031e27ea4157a-64bit'.. Downloading: /home/nitt/Projects/WASM2/emsdk/zips/1eec24930cb2f56f6d9cd10ffcb031e27ea4157a-wasm-binaries.tbz2 from https://storage.googleapis.com/webassembly/emscripten-releases-builds/linux/1eec24930cb2f56f6d9cd10ffcb031e27ea4157a/wasm-binaries.tbz2, 349224945 Bytes Unpacking '/home/nitt/Projects/WASM2/emsdk/zips/1eec24930cb2f56f6d9cd10ffcb031e27ea4157a-wasm-binaries.tbz2' to '/home/nitt/Projects/WASM2/emsdk/upstream' Done installing tool 'releases-1eec24930cb2f56f6d9cd10ffcb031e27ea4157a-64bit'. Done installing SDK 'sdk-releases-1eec24930cb2f56f6d9cd10ffcb031e27ea4157a-64bit'. [email protected]:~/Projects/WASM2/emsdk$ ./emsdk activate latest Resolving SDK alias 'latest' to '3.1.31' Resolving SDK version '3.1.31' to 'sdk-releases-1eec24930cb2f56f6d9cd10ffcb031e27ea4157a-64bit' Setting the following tools as active: node-14.18.2-64bit releases-1eec24930cb2f56f6d9cd10ffcb031e27ea4157a-64bit Next steps: - To conveniently access emsdk tools from the command line, consider adding the following directories to your PATH: /home/nitt/Projects/WASM2/emsdk /home/nitt/Projects/WASM2/emsdk/node/14.18.2_64bit/bin /home/nitt/Projects/WASM2/emsdk/upstream/emscripten - This can be done for the current shell by running: source "/home/nitt/Projects/WASM2/emsdk/emsdk_env.sh" - Configure emsdk in your shell startup scripts by running: echo 'source "/home/nitt/Projects/WASM2/emsdk/emsdk_env.sh"' >> $HOME/.bash_profile
Den siste kommandoen, «source ./emsdk_env.sh», sørger for at verktøystien for emcc Emscripten-kompilatoren settes, slik at du kan bruke den til å kompilere kode.
#Output [email protected]:~/Projects/WASM2/emsdk$ source ./emsdk_env.sh Setting up EMSDK environment (suppress these messages with EMSDK_QUIET=1) Adding directories to PATH: PATH += /home/nitt/Projects/WASM2/emsdk PATH += /home/nitt/Projects/WASM2/emsdk/upstream/emscripten PATH += /home/nitt/Projects/WASM2/emsdk/node/14.18.2_64bit/bin Setting environment variables: PATH = /home/nitt/Projects/WASM2/emsdk:/home/nitt/Projects/WASM2/emsdk/upstream/emscripten:/home/nitt/Projects/WASM2/emsdk/node/14.18.2_64bit/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin EMSDK = /home/nitt/Projects/WASM2/emsdk EMSDK_NODE = /home/nitt/Projects/WASM2/emsdk/node/14.18.2_64bit/bin/node [email protected]:~/Projects/WASM2/emsdk$
Nå må vi generere WASM-koden ved å kjøre følgende kommando.
emcc hello-tipsbilk.net.c -o hello-tipsbilk.net.js
#Output [email protected]:~/Projects/WASM2$ emcc hello-tipsbilk.net.c -o hello-tipsbilk.net.js shared:INFO: (Emscripten: Running sanity checks) cache:INFO: generating system asset: symbol_lists/1c683af19e290d0b5ca7a8747d74a76f63dcb362.txt... (this will be cached in "/home/nitt/Projects/WASM2/emsdk/upstream/emscripten/cache/symbol_lists/1c683af19e290d0b5ca7a8747d74a76f63dcb362.txt" for subsequent builds) cache:INFO: - ok [email protected]:~/Projects/WASM2$ dir emsdk hello-tipsbilk.net.c hello-tipsbilk.net.js hello-tipsbilk.net.wasm [email protected]:~/Projects/WASM2$
Som du kan se, genereres filene «hello-tipsbilk.net.js» og hello-tipsbilk.net.wasm. Du kan undersøke filene ved å kjøre kommandoen «dir» i prosjektmappen.
Begge disse filene er viktige. «hello-tipsbilk.net.wasm» inneholder den kompilerte koden. Filen «hello-tipsbilk.net.js» inneholder JavaScript-koden som trengs for å kjøre den. Ettersom Emscripten støtter både web- og node.js-utførelse, kan vi teste det med Node.
node hello-tipsbilk.net.js
#Output [email protected]:~/Projects/WASM2$ node hello-tipsbilk.net.js Hello, tipsbilk.net! [email protected]:~/Projects/WASM2$
Hvis du ønsker å se det kjøre på nettet, kan du generere en HTML-fil med Emscripten. For å gjøre dette, bruk følgende kommando.
emcc hello-tipsbilk.net.c -o hello-tipsbilk.net.html
#Output [email protected]:~/Projects/WASM2$ emcc hello-tipsbilk.net.c -o hello-tipsbilk.net.html [email protected]:~/Projects/WASM2$
For å kjøre HTML-filen, kan du bruke Python 3 HTTPServer ved å kjøre følgende kommando.
python3 -m http.server 8000
Gå deretter til http://localhost:8000/hello-tipsbilk.net.html for å se resultatet.
Merk: De fleste systemer leveres med forhåndsinstallert Python. Hvis ikke, kan du enkelt installere det før du prøver å kjøre Python3-serveren.
Bruk av JavaScript API for å arbeide med WASM
I denne delen skal vi se nærmere på JavaScript WASM API. Ved hjelp av dette vil vi lære hvordan du laster inn og utfører WASM-kode. Men la oss først se på koden nedenfor.
fetch('hello-tipsbilk.net.wasm').then( response => response.arrayBuffer()) .then (bytes => WebAssembly.instantiate(bytes)) .then(result=> alert(result.instance.exports.answer()))
Koden ovenfor bruker følgende JavaScript API-er.
- fetch() nettleser-API
- WebAssembly.instantiate
I tillegg finnes det flere andre API-er som er verdt å merke seg. Disse inkluderer:
- WebAssembly.compile
- WebAssembly.instance
- WebAssembly.instantiate
- WebAssembly.instantiateStreaming
fetch() nettleser-API
Fetch() API-et laster inn .wasm-nettverksressursen. Hvis du prøver å laste den inn lokalt, må du deaktivere kryssopprinnelsesressursdeling for å laste nettverksressursen. Alternativt kan du bruke en nodeserver for å utføre dette. For å installere og kjøre en nodeserver, kjør følgende kommando.
sudo apt install npm
Deretter kjører du følgende kommando for å starte serveren.
npx http-server -o
#Output http-server version: 14.1.1 http-server settings: CORS: disabled Cache: 3600 seconds Connection Timeout: 120 seconds Directory Listings: visible AutoIndex: visible Serve GZIP Files: false Serve Brotli Files: false Default File Extension: none Available on: http://127.0.0.1:8080 http://192.168.0.107:8080 Hit CTRL-C to stop the server Open: http://127.0.0.1:8080 [2023-01-28T19:22:21.137Z] "GET /" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36 Edg/109.0.1518.70" (node:37919) [DEP0066] DeprecationWarning: OutgoingMessage.prototype._headers is deprecated (Use `node --trace-deprecation ...` to show where the warning was created) [2023-01-28T19:22:21.369Z] "GET /favicon.ico" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36 Edg/109.0.1518.70" [2023-01-28T19:22:21.369Z] "GET /favicon.ico" Error (404): "Not found"
Dette åpner nettleseren, hvor du kan se alle prosjektfilene dine.
Åpne nå «hello-tipsbilk.net.html» og aktiver utviklerverktøyene i nettleseren. Deretter åpner du konsollen og skriver inn følgende.
fetch(“hello-tipsbilk.net.wasm”);
Dette vil returnere følgende promise.
#Output Promise {<pending>} [[Prototype]]: Promise [[PromiseState]]: "fulfilled" [[PromiseResult]]: Response body: (...) bodyUsed: false headers: Headers {} ok: true redirected: false status: 200 statusText: "OK" type: "basic" url: "http://127.0.0.1:8080/hello-tipsbilk.net.wasm" [[Prototype]]: Response
Du kan også skrive følgende skript og kjøre det i HTML-filen.
For å kjøre WASM-modulene dine på serveren, kan du bruke følgende kode i Node.js.
const fs = require('fs'); const run = async() => { const buffer = fs.readFileSync("./hello-tipsbilk.net.wasm"); const result = await WebAssembly.instantiate(buffer); console.log(result.instance.exports.answer()); }; run();
Vi anbefaler at du leser dokumentasjonen for WebAssembly JavaScript API for å lære mer om dette.
JavaScript vs. WASM
For å få en dypere forståelse av forholdet mellom WASM og JavaScript, må vi sammenligne dem. I bunn og grunn er WASM raskere og har et binært format for kompilering, mens JavaScript er et høynivåspråk. Den binære koden til WASM gjør det vanskeligere å lære, men det finnes metoder for å jobbe med WASM effektivt.
De viktigste forskjellene mellom WASM og JavaScript inkluderer følgende:
- WASM er et kompilert språk, mens JS er et tolket språk. Nettleseren må laste ned og analysere JavaScript under kjøring, mens WASM-koden er klar til å kjøres med sin forhåndskompilerte kode.
- WebAssembly er et lavnivåspråk. Derimot er JavaScript et høynivåspråk. JS er på et høyt nivå og er derfor enklere å jobbe med. Imidlertid kan WASM på et lavt nivå kjøre mye raskere enn JavaScript.
- Til slutt drar JavaScript nytte av et stort fellesskap. Så hvis du er ute etter en bedre utviklingsopplevelse, er JS et opplagt valg. WebAssembly er derimot relativt nytt og mangler derfor ressurser.
Som utvikler trenger du ikke å bekymre deg for å velge en av dem. Dette er fordi JS og WASM jobber sammen, ikke mot hverandre.
Så hvis du utvikler en app med høy ytelse, kan det være fordelaktig å bruke WebAssembly til å kode de delene som trenger den ekstra ytelsen. JavaScript API-et kan hjelpe deg med å laste og bruke WASM-moduler direkte i JavaScript-koden din.
Avsluttende tanker
WebAssembly er en fantastisk medspiller for JavaScript. Det åpner for at utviklere kan skape applikasjoner med høy ytelse både på web og utenfor web. I tillegg gjør det dette uten å forsøke å erstatte JavaScript.
Men vil WASM utvikle seg til en fullstendig pakke og overta JavaScript sin rolle? Vel, det er ikke usannsynlig, med tanke på WebAssemblys mål. Men tanken om at WebAssembly erstatter JavaScript i fremtiden, er ikke helt utelukket.
Nå anbefaler vi at du tar en titt på de beste JavaScript (JS) UI-bibliotekene for å utvikle moderne applikasjoner.