de Daniel Simmons

Începeți cu WebAssembly – folosind doar 14 linii de JavaScript

Incepeti cu WebAssembly folosind doar 14 linii de JavaScript

WebAssembly este o tehnologie web nouă cu potențial masiv. Acesta va avea un impact semnificativ asupra modului în care sunt dezvoltate aplicațiile web în viitor.

Dar, uneori, simt că pur și simplu nu vrea să fie înțeles … aproape într-un mod ciudat pasiv-agresiv.

Când mă uit la documentație și la o mână de tutoriale care sunt deja acolo, nu mă pot abține să nu mă simt ca un fermier care s-a rugat pentru ploaie, doar pentru a se îneca într-un potop. Din punct de vedere tehnic am obținut ceea ce îmi doream … doar nu așa cum speram. „Vrei ploaie ?! Oh, îți dau ploaie! ”

Acest lucru se datorează faptului că WebAssembly face posibilă atâtea lucruri noi și poate fi implementat în atât de multe moduri diferite. Dar, s-a schimbat atât de mult pe parcurs lansarea oficială a MVP în februarie, că atunci când începeți să aflați despre asta, este ușor să vă înecați într-o mare de detalii.

Continuând metafora ploii, acest articol este încercarea mea de a oferi un duș ușor de introducere la WebAssembly. Nu conceptele sau piulițele, ci implementarea efectivă.

Vă voi parcurge pașii pentru a crea și implementa un proiect extrem de simplu, eliminând complexitatea ori de câte ori este posibil. După ce l-ați implementat o dată, oricât de simplu, multe dintre aceste idei de nivel superior sunt mult mai ușor de înțeles.

Să o descompunem

Totul va fi mult mai clar dacă ne întoarcem și analizăm o listă cu pașii implicați în implementarea WebAssembly într-un proiect.

Când începeți pentru prima dată, este ușor să vă uitați la WebAssembly și să vedeți doar o mulțime de opțiuni și procese. Descompunerea în pași discreți ne va ajuta să obținem o imagine clară a ceea ce se întâmplă:

  1. Scrie: Scrieți ceva (sau utilizați un proiect existent) în C, C ++ sau Rust
  2. Compila: Compilați-l în WebAssembly (oferindu-vă un fișier binar .wasm)
  3. Include: Introduceți acel fișier .wasm într-un proiect
  4. Instantați: Scrieți o grămadă de JavaScript asincrone care vor compila binarul .wasm și îl vor crea în ceva cu care JS se poate juca frumos.

Și cam atât. Desigur, există diferite permutări ale acestui proces, dar acesta este esența acestuia.

În linii mari, nu este atât de complicat. Cu toate acestea, ea poate sa devin extrem de complicate, deoarece majoritatea acestor pași permit graduri de complexitate foarte variate. În fiecare caz, voi greși din partea simplității cu oase goale.

Pentru proiectul nostru, vom scrie o funcție simplă în C ++ (nu vă faceți griji dacă nu sunteți familiarizat cu C ++, va fi extrem simplu). Funcția va returna pătratul unui număr dat.

Apoi, îl vom compila în .wasm folosind un instrument online (nu va trebui să descărcați sau să utilizați niciun utilitar din linia de comandă). Apoi, o vom instanția cu 14 linii de JS.

Când am terminat, veți putea apela o funcție scrisă în C ++ ca și cum ar fi o funcție JS și veți fi uimiți!

Numărul mare de posibilități pe care le deschide acest lucru este absolut minunat.

Scrie

Să începem cu codul nostru C ++. Amintiți-vă, nu vom folosi un mediu de dezvoltare local pentru a scrie sau compila acest lucru.

În schimb, vom folosi un instrument online numit WebAssembly Explorer. Este un fel de CodePen pentru WebAssembly și vă permite să vă compilați codul C sau C ++ chiar în browser și să descărcați un fișier .wasm totul într-un singur loc.

După ce ați deschis WebAssembly Explorer, tastați acest cod C ++ în fereastra din stânga:

int squarer(int num) {  return num * num;}

Așa cum am spus, folosim un exemplu foarte simplu aici. Chiar dacă nu v-ați uitat niciodată la C sau C ++ înainte, probabil că nu este prea dificil să spuneți ce se întâmplă.

Compila

Apoi, faceți clic pe butonul care scrie „compilați” în bara roșie de deasupra codului dvs. C ++. Iată ce veți vedea:

Incepeti cu WebAssembly folosind doar 14 linii de JavaScript

Coloana din mijloc vă arată o versiune lizibilă de om a binarului .wasm pe care tocmai l-ați creat. Aceasta se numește „WAT” sau WebAssembly Text Format.

În dreapta este codul de asamblare rezultat. Destul de la moda.

Nu voi intra în prea multe detalii despre oricare dintre acestea, dar trebuie să știți cel puțin puțin despre fișierul WAT pentru a urma pașii următori.

WAT există pentru că noi, oamenii, în general, avem dificultăți în a înțelege binele drept. Este în esență un strat de abstractizare care vă ajută să înțelegeți și să interacționați cu codul dvs. WebAssembly.

În cazul nostru, ceea ce vrem să înțelegem este modul în care WebAssembly-ul nostru se referă la funcția pe care tocmai am creat-o. Asta pentru că va trebui să folosim același nume exact în fișierul nostru JS mai târziu pentru a ne referi la acesta.

Orice funcție pe care o scrieți în codul dvs. C ++ va fi disponibilă în WebAssembly ca ceva numit „export”. Vom vorbi puțin mai mult despre asta mai târziu, dar pentru moment, tot ce trebuie să știți este că exporturile sunt lucrurile cu care veți putea interacționa și utiliza.

Aruncați o privire la fișierul WAT și căutați cuvântul „export”. O veți vedea de două ori: o dată alături de cuvânt memory și din nou alături de cuvânt _Z7squareri. Nu trebuie să știm despre memory deocamdată, dar cu siguranță ne interesează _Z7squareri.

Am folosit numele funcției squarer în C ++, dar acum asta a devenit cumva _z7squareri. Acest lucru poate fi cu siguranță confuz atunci când îl vedeți prima dată.

Din câte îmi dau seama, prefixul „_Z7” și sufixul „i” sunt marcatori de depanare introdus de compilatorul C ++. Totuși, acest lucru nu este foarte important pentru a înțelege în profunzime. Trebuie doar să știți că acest lucru se va întâmpla, deoarece trebuie să utilizați acest nume exact în fișierul dvs. JS pentru a apela funcția dvs. C ++.

Include

Acum, faceți clic pe butonul „Descărcați” din partea de sus a secțiunii violet WAT. Veți obține fișierul binar .wasm. Redenumiți-l squarer.wasm. Apoi creați un nou director și puneți-l squarer.wasm fișier acolo, împreună cu alte două fișiere:

  • index.html (cazan)
  • scripts.js (gol pentru moment)

Instantați

Acum, pentru partea dificilă. Sau, cel puțin, partea care mi-a provocat o mulțime de confuzie când am început să trec prin cercetare documentația.

Deși în cele din urmă veți putea include module .wasm, cum ar fi un vechi modul ES6 obișnuit (folosind <script type="module “>), deocamdată trebuie să-l configurați„ manual ”. Acest lucru se face efectuând o grămadă de apeluri asincrone către API-ul WebAssembly. Există trei pași:

  • Introduceți fișierul dvs. binar .wasm într-un fișier tampon matrice *
  • Compilați octeții într-un WebAssembly modul*
  • Instantaneu * modulul WebAssembly

Dacă toate acestea au sens pentru dvs., puteți trece la următoarea secțiune. Dar dacă te-ai trezit zgâriind puțin capul și vrei o explicație mai detaliată, atunci continuă să citești.

* Array Buffer

Un buffer este un loc de stocare temporar pentru date în timp ce este mutat. În general, acest lucru este util atunci când datele sunt primite și procesate la rate diferite.

De exemplu, atunci când un videoclip este în memorie tampon, datele sunt recepționate cu o viteză mai lentă decât poate fi redat de playerul video. Unul dintre lucrurile pe care le face buffer-ul nostru de matrice este așteptarea datelor noastre binare, astfel încât să poată fi compilate mai ușor.

Dar se întâmplă altceva foarte important aici. În JavaScript, un buffer de matrice este un matricea tastată, care este ceva folosit special pentru stocarea datelor binare.

Faptul că este tastat în mod explicit înseamnă că motorul JS poate interpreta un buffer de matrice mult mai repede decât poate un array obișnuit, deoarece știe deja tipul de date și nu trebuie să treacă prin procesul de identificare a acestuia.

* Modul WebAssembly

Odată ce ați introdus toate datele binare într-un buffer de matrice, le puteți compila într-un modul. Modulul WebAssembly este, în sine, inert. Este doar binele compilat, care așteaptă să se facă ceva cu el.

Aproape că vă puteți gândi la modul ca la o rețetă de tort. Rețeta este doar un format pentru stocarea informațiilor despre modul de preparare a unui tort. Dacă doriți de fapt un tort, trebuie să creați o instanță a tortului descris în rețetă (instanțiați tortul).

Faceți acest lucru urmând instrucțiunile prezentate în rețetă. Alternativ, puteți trimite rețeta altcuiva (un „lucrător de service”) sau o puteți salva și utiliza mai târziu („cache”). Ambele sunt mult mai convenabile de făcut cu o rețetă, decât cu un tort propriu-zis.

* Instantați

Ultimul lucru pe care trebuie să-l faceți este să creați o instanță a modulului dvs. WebAssembly, care „îl aduce la viață” și îl face efectiv utilizabil.

Instanța vă oferă acces la exporturile modulului (vă amintiți acest lucru din fișierul nostru WAT?). Acesta este un obiect care conține:

  • Memorie (nu este relevantă pentru noi, dar puteți citi mai multe despre aceasta Aici)
  • Orice funcții care erau prezente în codul dvs. C ++. Acesta este modul în care veți utiliza funcția C ++ pe care ați scris-o.

Termină și rulează-l!

Iată codul care realizează toți pașii pe care tocmai l-am parcurs (acest lucru intră în scripts.js fişier):

loadWebAssembly() funcția preia fișierul .wasm și apoi efectuează operațiunile menționate mai sus. Apoi returnează o nouă instanță a modulului WebAssembly.

Funcția noastră C ++ (amintiți-vă că este menționată de numele funky menționat anterior: _z7squareri ) locuiește în exporturile proprietate ale instanței noastre. Puteți vedea că este atribuită variabilei globale squarer pe linia 12. Acum putem folosi squarer() ca o funcție JavaScript obișnuită!

Odată ce ai pus asta în scripts.js fișier și apăsați salvare, îl puteți trage în sus pe localhost și ar trebui să vedeți mesajul „Finalizat compilarea …” în consolă.

Acum, trebuie doar să apelați funcția dvs. și să transmiteți un argument din consolă. Încercați ceva de genul squarer(9) . Apăsați return și veți vedea 81 . Funcționează! Apelați o funcție scrisă în C ++!

1611926351 222 Incepeti cu WebAssembly folosind doar 14 linii de JavaScript

Asta este fantastic

Vă puteți imagina toate lucrurile pe care acest lucru le face posibile.

În primul rând, JavaScript nu mai este singura opțiune pentru „a face lucruri” în browser. Asta este absolut imens.

Apoi, există îmbunătățiri de performanță, deoarece WebAssembly, spre deosebire de JS, rulează la o viteză aproape nativă.

Și apoi există tot codul vechi care este acum la dispoziția ta. C și C ++ există de multă vreme și, în acel timp, o mulțime de oameni străluciți au creat cu el niște proiecte open source uimitoare. Proiecte care pot fi acum integrate în site-uri web sau aplicații.

De aici, puteți scrie coduri C, C ++ sau Rust mai complexe sau chiar adaptați un proiect existent și „wasm-it” într-un proiect web.

Cu toate acestea, un avertisment este că, dacă doriți să creați funcții care acceptă argumente sau să returneze valori care nu sunt numere, atunci lucrurile încep să devină puțin mai complicate. Atunci va trebui să aflați mai multe despre atributul de memorie al exporturilor instanței .wasm.

Acest proiect este disponibil pe GitHub dacă doriți doar să clonați o copie de lucru pe lângă faptul că urmați împreună cu articolul.