Грунд за WebAssembly: Започнете с WebAssembly

WebAssembly обещава изцяло нов вид мрежа - по-бърза производителност за потребителите и по-голяма гъвкавост за разработчиците. Вместо да бъде заключен да използва JavaScript като единствен език за уеб взаимодействие от страна на клиента, разработчикът може да избира от широк спектър от други езици - C, TypeScript, Rust, Ruby, Python - и да работи на този, който им е най-удобен с.

Първоначално единственият начин за създаване на WebAssembly (или накратко WASM) беше компилирането на C / C ++ код в WebAssembly с помощта на веригата от инструменти Emscripten. Днес разработчиците не само имат повече езикови опции, но стана по-лесно да компилирате тези други езици директно в WebAssembly, с по-малко интервенционни стъпки.

В тази част ще разгледаме стъпките, необходими за внедряване на компоненти WebAssembly в уеб приложение. Тъй като WebAssembly е в процес на разработка, стъпките силно зависят от това кой език използвате и веригата от инструменти вероятно ще продължи да се променя известно време. Но в момента е възможно да пишете и разполагате полезни, ако не и минимални, WebAssembly приложения на редица езици.

Изберете език, поддържан от WebAssembly

Първата стъпка към внедряването на приложение WebAssembly е да изберете език, който може да се компилира в WebAssembly като цел. Има голям шанс поне един от основните езици, които използвате в производството, да бъде преобразуван в WebAssembly или има компилатор, който може да излъчва WebAssembly.

Ето предните участници:

  • В. Очевидно. Типичният начин за превръщане на C кода в WebAssembly е чрез Emscripten, тъй като C-to-Emscripten-to-WebAssembly е първата верига от инструменти WebAssembly, която се появява. Но се появяват други инструменти. Цял компилатор, Cheerp, е проектиран специално за генериране на WebAssembly приложения от C / C ++ код. Cheerp може също да насочва JavaScript, asm.js или всяка комбинация от горното. Също така е възможно да се използва веригата инструменти на Clang за изграждане на полезни натоварвания на WebAssembly, въпреки че процесът все още изисква доста ръчно повдигане. (Ето един пример.)
  • Ръжда. Системи на Mozilla език за програмиране, предназначени да бъдат едновременно безопасен и бърз, е един от основните кандидати за родния подкрепа WebAssembly. Разширенията на веригата с инструменти Rust ви позволяват да компилирате директно от кода на Rust до WebAssembly. Трябва да използвате nightlyверигата с инструменти на Rust, за да извършите компилация на WebAssembly, така че засега тази функция трябва да се счита за експериментална.
  • TypeScript . По подразбиране TypeScript се компилира в JavaScript, което означава, че от своя страна може да се компилира в WebAssembly. Проектът AssemblyScript намалява броя на участващите стъпки, позволявайки строго набрания TypeScript да бъде компилиран в WebAssembly.

Няколко други езика започват да насочват към WebAssembly, но те са в много ранен етап. Следните езици могат да се използват за изграждане на компоненти WebAssembly, но само по по-ограничени начини от C, Rust и TypeScript:

  • D . Езикът D наскоро добави поддръжка за компилиране и свързване директно към WebAssembly.
  • Java . Байтовият код на Java може да бъде компилиран преди време в WebAssembly чрез проекта TeaVM. Това означава, че всеки език, който излъчва байт код на Java, може да бъде компилиран в WebAssembly - например Kotlin, Scala или Clojure. Въпреки това, много от API на Java, които не могат да бъдат внедрени ефективно в WebAssembly, са ограничени, като API за отражение и ресурси, така че TeaVM - и по този начин WebAssembly - се използва само за подмножество от приложения, базирани на JVM. 
  • Луа . Скриптовият език Lua има дълга история на използване като вграден език, точно като JavaScript. Единствените проекти, които превръщат Lua в WebAssembly, включват използване на механизъм за изпълнение в браузъра: wasm_lua вгражда време за изпълнение на Lua в браузъра, докато Luwa JIT компилира Lua в WebAssembly.
  • Котлин / Роден . Феновете на езика Kotlin, spinoff на Java, с нетърпение очакват пълното издание на Kotlin / Native, LLVM заден край на компилатора Kotlin, който може да създаде самостоятелни двоични файлове. Kotlin / Native 0.4 въведе поддръжка за WebAssembly като цел за компилация, но само като доказателство за концепцията.
  • .Нет . Езиците .Net все още нямат пълноценна поддръжка на WebAssembly, но някои експерименти са започнали. Вижте Blazor, който може да се използва за създаване на уеб страници с една страница в .Net чрез C # и синтаксиса „Razor“ на Microsoft.
  • Ним . Този предстоящ език се компилира в C, така че на теория може да се компилира полученото C в WebAssembly. Въпреки това, експериментален заден край за Ним, наречен nwasm, се разработва.
  • Други LLVM езици . На теория всеки език, който използва рамката на компилатора LLVM, може да бъде компилиран в WebAssembly, тъй като LLVM поддържа WebAssembly като една от многото цели. Това обаче не означава непременно, че всеки компилиран от LLVM език ще работи както е в WebAssembly. Това просто означава, че LLVM улеснява насочването към WebAssembly.

Всички горепосочени проекти преобразуват оригиналната програма или генерирания байт код в WebAssembly. Но за интерпретираните езици като Ruby или Python има друг подход: Вместо да конвертирате самите приложения, човек преобразува времето за изпълнение на езика  в WebAssembly. След това програмите се изпълняват както е в преобразуваното изпълнение. Тъй като много езикови изпълнения (включително Ruby и Python) са написани на C / C ++, процесът на преобразуване е по същество същият като при всяко друго приложение на C / C ++.

Разбира се, това означава, че преобразуваното изпълнение трябва да бъде изтеглено в браузъра, преди да могат да се стартират приложения с него, забавяйки времето за зареждане и анализиране. „Чистата“ версия на приложението WebAssembly е по-лека. По този начин преобразуването по време на изпълнение е в най-добрия случай ограничителна мярка, докато повече езици не поддържат WebAssembly като цел за износ или компилация.

Интегрирайте WebAssembly с JavaScript

Следващата стъпка е да напишете код на избрания от вас език, като обърнете внимание на това как този код ще взаимодейства със средата WebAssembly, след това да го компилирате в модул WebAssembly (двоичен файл на WASM) и накрая да интегрирате този модул със съществуващ Приложение на JavaScript.

Точните стъпки за това как да експортирате кода в WebAssembly ще варират значително в зависимост от веригата с инструменти. Те също така ще се отклоняват донякъде от начина, по който се изграждат редовни бинарни файлове за този език. Например в Rust ще трябва да изпълните няколко стъпки:

  1. Настройте nightly компилацията за Rust с wasm32-unknown-unknownверигата от инструменти.
  2. Напишете вашия Rust код с външни функции, декларирани като #[no-mangle].
  3. Изградете кода, като използвате горната верига от инструменти.

(За подробен преглед на горните стъпки вижте The Rust and WebAssembly Book на GitHub.)

Струва си да се отбележи, че какъвто и език да използвате, ще трябва да имате поне минимално ниво на владеене на JavaScript, за да интегрирате кода с предния край на HTML. Ако фрагментите на JavaScript на страницата в този пример от The Rust and WebAssembly Book ви се струват гръцки, отделете малко време за изучаване на поне достатъчно JavaScript, за да разберете какво се случва там.

Интегрирането на WebAssembly и JavaScript се извършва чрез използване на WebAssemblyобекта в JavaScript за създаване на мост към вашия WebAssembly код. Mozilla разполага с документация за това как да направите това. Ето отделен пример за WebAssembly за Rust и ето пример за WebAssembly за Node.js.

В момента интеграцията между WebAssembly back end и JavaScript / HTML front end все още е най-тромавата и ръчна част от целия процес. Например с Rust мостовете към JavaScript все още трябва да се създават ръчно чрез указатели на сурови данни.

Въпреки това, повече части от веригата с инструменти започват да се занимават с този проблем. Рамката Cheerp позволява на програмистите на C ++ да говорят с API на браузъра чрез специално пространство от имена. И Rust предлага wasm-bindgen, който служи като двупосочен мост между JavaScript и Rust и между JavaScript и WebAssembly.

Освен това се обсъжда предложение на високо ниво за това как да се обработват обвързванията към хоста. След като бъде финализиран, той ще осигури стандартен начин за взаимодействие на езици, които се компилират към WebAssembly, с хостове. Дългосрочната стратегия с това предложение също включва обвързване към хостове, които не са браузъри, но обвързването на браузъра е краткосрочен случай за незабавна употреба.

Отстраняване на грешки и профилиране на приложения WebAssembly

Една област, в която инструментариумът WebAssembly все още е в най-ранните етапи, е поддръжката за отстраняване на грешки и профилиране. 

Докато не се появиха изходните карти на JavaScript, езиците, които се компилираха в JavaScript, често бяха трудни за отстраняване на грешки, тъй като оригиналният и компилираният код не можеха да бъдат лесно свързани. WebAssembly има едни и същи проблеми: Ако напишете код в C и го компилирате в WASM, е трудно да се направят корелации между източника и компилирания код.

Изходните карти на JavaScript показват кои редове в изходния код съответстват на кои региони на компилирания код. Някои инструменти за WebAssembly, като Emscripten, също могат да излъчват изходни карти на JavaScript за компилиран код. Един от дългосрочните планове за WebAssembly е система с изходни карти, която надхвърля само това, което се предлага в JavaScript, но все още е само на етапа на предложението.

В момента най-прекият начин за отстраняване на грешки в WASM кода в дивата природа е чрез конзолата за отстраняване на грешки на уеб браузъра. Тази статия в WebAssemblyCode показва как да генерирате WASM код с изходна карта, да го направите достъпен за инструментите за отстраняване на грешки в браузъра и да преминете през кода. Имайте предвид, че описаните стъпки зависят от използването на emccинструмента за излъчване на WASM. Може да се наложи да промените стъпките в зависимост от вашата конкретна верига от инструменти.