Primer WebAssembly: Memulai WebAssembly

WebAssembly menjanjikan jenis web yang benar-benar baru — kinerja yang lebih tajam untuk pengguna, dan lebih banyak fleksibilitas untuk pengembang. Daripada dikunci untuk menggunakan JavaScript sebagai satu-satunya bahasa untuk interaksi web sisi klien, pengembang dapat memilih dari berbagai bahasa lain — C, TypeScript, Rust, Ruby, Python — dan bekerja dengan bahasa yang paling nyaman. dengan.

Awalnya, satu-satunya cara untuk membuat WebAssembly (atau disingkat WASM) adalah dengan mengkompilasi kode C / C ++ ke WebAssembly menggunakan toolchain Emscripten. Saat ini, tidak hanya pengembang memiliki lebih banyak pilihan bahasa, tetapi juga menjadi lebih mudah untuk mengkompilasi bahasa lain ini langsung ke WebAssembly, dengan lebih sedikit langkah intervensi.

Dalam bagian ini, kita akan memeriksa langkah-langkah yang diperlukan untuk mengimplementasikan komponen WebAssembly di aplikasi web. Karena WebAssembly masih dalam proses, langkah-langkahnya sangat bergantung pada bahasa yang Anda gunakan, dan toolchain kemungkinan akan terus berubah untuk beberapa waktu. Tapi sekarang, mungkin untuk menulis dan menyebarkan aplikasi WebAssembly yang berguna, jika minimal, dalam sejumlah bahasa.

Pilih bahasa yang didukung WebAssembly

Langkah pertama untuk menerapkan aplikasi WebAssembly adalah memilih bahasa yang dapat dikompilasi ke WebAssembly sebagai target. Ada kemungkinan besar bahwa setidaknya salah satu bahasa utama yang Anda gunakan dalam produksi dapat dikonversi ke WebAssembly, atau memiliki kompiler yang dapat mengeluarkan WebAssembly.

Berikut adalah pelari terdepan:

  • C. Jelas. Cara khas untuk mengubah kode C menjadi WebAssembly adalah melalui Emscripten, karena C-to-Emscripten-to-WebAssembly adalah toolchain WebAssembly pertama yang muncul. Tetapi alat lain sedang bermunculan. Seluruh kompiler, Cheerp, telah direkayasa secara khusus untuk menghasilkan aplikasi WebAssembly dari kode C / C ++. Cheerp juga dapat menargetkan JavaScript, asm.js, atau kombinasi apa pun di atas. Anda juga dapat menggunakan toolchain Clang untuk membangun muatan WebAssembly, meskipun prosesnya masih memerlukan banyak pengangkatan manual. (Ini salah satu contohnya.)
  • Karat. Bahasa pemrograman sistem Mozilla, yang dirancang agar aman dan cepat, adalah salah satu kandidat utama untuk dukungan WebAssembly asli . Ekstensi pada toolchain Rust memungkinkan Anda mengkompilasi langsung dari kode Rust ke WebAssembly. Anda perlu menggunakan nightlytoolchain Rust untuk melakukan kompilasi WebAssembly, jadi fitur ini harus dianggap eksperimental untuk saat ini.
  • TypeScript . Secara default TypeScript dikompilasi ke JavaScript, yang berarti bahwa itu pada gilirannya dapat dikompilasi ke WebAssembly. Proyek AssemblyScript mengurangi jumlah langkah yang terlibat, memungkinkan TypeScript yang diketik dengan ketat untuk dikompilasi ke WebAssembly.

Beberapa bahasa lain mulai menargetkan WebAssembly, tetapi masih dalam tahap yang sangat awal. Bahasa berikut dapat digunakan untuk membangun komponen WebAssembly, tetapi hanya dengan cara yang lebih terbatas daripada C, Rust, dan TypeScript:

  • D . Bahasa D baru-baru ini menambahkan dukungan untuk kompilasi dan tautan langsung ke WebAssembly.
  • Jawa . Bytecode Java dapat dikompilasi sebelumnya ke WebAssembly melalui proyek TeaVM. Artinya, bahasa apa pun yang mengeluarkan bytecode Java dapat dikompilasi ke WebAssembly — misalnya, Kotlin, Scala, atau Clojure. Namun, banyak Java API yang tidak dapat diterapkan secara efisien di WebAssembly dibatasi, seperti API refleksi dan resource, sehingga TeaVM — dan WebAssembly — hanya digunakan untuk subset aplikasi berbasis JVM. 
  • Lua . Bahasa skrip Lua memiliki sejarah panjang penggunaan sebagai bahasa yang disematkan, seperti JavaScript. Namun, satu-satunya proyek untuk mengubah Lua menjadi WebAssembly melibatkan penggunaan mesin eksekusi dalam browser: wasm_lua menyematkan runtime Lua di browser, sementara Luwa JIT mengkompilasi Lua ke WebAssembly.
  • Kotlin / Native . Penggemar bahasa Kotlin, sebuah spin-off dari Java, telah menunggu rilis lengkap Kotlin / Native, back end LLVM untuk compiler Kotlin yang dapat menghasilkan biner yang berdiri sendiri. Kotlin / Native 0.4 memperkenalkan dukungan untuk WebAssembly sebagai target kompilasi, tetapi hanya sebagai bukti konsep.
  • .Net . Bahasa .Net belum memiliki dukungan WebAssembly yang lengkap, tetapi beberapa eksperimen telah dimulai. Lihat Blazor, yang dapat digunakan untuk membangun aplikasi web satu halaman di .Net via C # dan sintaks "Razor" Microsoft.
  • Nim . Bahasa yang sedang naik daun ini mengkompilasi ke C, jadi secara teori seseorang dapat mengkompilasi C yang dihasilkan ke WebAssembly. Namun, back end eksperimental untuk Nim yang disebut nwasm sedang dikembangkan.
  • Bahasa lain yang didukung LLVM . Secara teori, bahasa apa pun yang memanfaatkan framework compiler LLVM dapat dikompilasi ke WebAssembly, karena LLVM mendukung WebAssembly sebagai salah satu dari banyak target. Namun, ini tidak berarti bahwa bahasa yang dikompilasi LLVM akan berjalan sebagaimana adanya di WebAssembly. Ini hanya berarti bahwa LLVM membuat penargetan WebAssembly lebih mudah.

Semua proyek di atas mengubah program asli atau bytecode yang dihasilkan menjadi WebAssembly. Tetapi untuk bahasa yang ditafsirkan seperti Ruby atau Python, ada pendekatan lain: Alih-alih mengubah aplikasi itu sendiri, seseorang mengubah runtime bahasa  menjadi WebAssembly. Program kemudian berjalan sebagaimana adanya pada runtime yang dikonversi. Karena banyak runtime bahasa (termasuk Ruby dan Python) ditulis dalam C / C ++, proses konversinya pada dasarnya sama dengan aplikasi C / C ++ lainnya.

Tentu saja ini berarti runtime yang dikonversi harus diunduh ke browser sebelum aplikasi apa pun dapat dijalankan dengannya, memperlambat waktu pemuatan dan penguraian. Versi aplikasi WebAssembly "murni" lebih ringan. Jadi konversi runtime paling baik merupakan ukuran sementara sampai lebih banyak bahasa mendukung WebAssembly sebagai target ekspor atau kompilasi.

Integrasikan WebAssembly dengan JavaScript

Langkah selanjutnya adalah menulis kode dalam bahasa yang Anda pilih, dengan memperhatikan bagaimana kode itu akan berinteraksi dengan lingkungan WebAssembly, kemudian mengkompilasinya ke dalam modul WebAssembly (biner WASM), dan akhirnya mengintegrasikan modul itu dengan yang sudah ada. Aplikasi JavaScript.

Langkah-langkah yang tepat tentang cara mengekspor kode ke WebAssembly akan sangat bervariasi bergantung pada toolchain. Mereka juga akan agak menyimpang dari cara biner asli biasa dibuat untuk bahasa itu. Misalnya, di Rust, Anda harus mengikuti beberapa langkah:

  1. Siapkan nightly build untuk Rust, dengan wasm32-unknown-unknowntoolchain.
  2. Tulis kode Rust Anda dengan fungsi eksternal yang dideklarasikan sebagai #[no-mangle].
  3. Buat kode menggunakan toolchain di atas.

(Untuk mengetahui detail langkah-langkah di atas, lihat The Rust and WebAssembly Book di GitHub.)

Perlu dicatat bahwa bahasa apa pun yang Anda gunakan, Anda harus memiliki setidaknya tingkat kemahiran minimal dalam JavaScript demi mengintegrasikan kode dengan front end HTML. Jika cuplikan JavaScript dalam halaman dalam contoh ini dari The Rust dan WebAssembly Book tampak seperti bahasa Yunani bagi Anda, luangkan waktu untuk mempelajari setidaknya cukup JavaScript untuk memahami apa yang terjadi di sana.

Integrasi WebAssembly dan JavaScript dilakukan dengan menggunakan WebAssemblyobjek di JavaScript untuk membuat jembatan ke kode WebAssembly Anda. Mozilla memiliki dokumentasi tentang cara melakukan ini. Berikut adalah contoh WebAssembly terpisah untuk Rust, dan berikut adalah contoh WebAssembly untuk Node.js.

Saat ini, integrasi antara back end WebAssembly dan front end JavaScript / HTML masih merupakan bagian yang paling rumit dan manual dari keseluruhan proses. Misalnya, dengan Rust, penghubung ke JavaScript masih harus dibuat secara manual, melalui penunjuk data mentah.

Namun, lebih banyak bagian dari toolchain yang mulai mengatasi masalah ini. Kerangka Cheerp memungkinkan programmer C ++ untuk berbicara dengan API browser melalui namespace khusus. Dan Rust menawarkan wasm-bindgen, yang berfungsi sebagai jembatan dua arah antara JavaScript dan Rust, dan antara JavaScript dan WebAssembly.

Selain itu, proposal tingkat tinggi tentang cara menangani binding ke host sedang dipertimbangkan. Setelah diselesaikan, ini akan memberikan cara standar untuk bahasa yang dikompilasi ke WebAssembly untuk berinteraksi dengan host. Strategi jangka panjang dengan proposal ini juga mencakup binding ke host yang bukan browser, tetapi binding browser adalah kasus penggunaan jangka pendek dan langsung.

Debugging dan membuat profil aplikasi WebAssembly

Satu area di mana perkakas WebAssembly masih dalam tahap paling awal adalah dukungan untuk debugging dan profiling. 

Sampai peta sumber JavaScript muncul, bahasa yang dikompilasi ke JavaScript seringkali sulit untuk di-debug karena kode asli dan yang dikompilasi tidak dapat dengan mudah dikorelasikan. WebAssembly memiliki beberapa masalah yang sama: Jika Anda menulis kode dalam C dan mengkompilasinya ke WASM, sulit untuk menggambar korelasi antara sumber dan kode yang dikompilasi.

Peta sumber JavaScript menunjukkan baris mana dalam kode sumber yang sesuai dengan region mana dari kode yang dikompilasi. Beberapa alat WebAssembly, seperti Emscripten, juga dapat memancarkan peta sumber JavaScript untuk kode yang dikompilasi. Salah satu rencana jangka panjang untuk WebAssembly adalah sistem peta sumber yang melampaui apa yang tersedia di JavaScript, tetapi masih dalam tahap proposal.

Saat ini, cara paling langsung untuk men-debug kode WASM di alam liar adalah dengan menggunakan konsol debug browser web. Artikel di WebAssemblyCode ini menunjukkan cara membuat kode WASM dengan peta sumber, membuatnya tersedia untuk alat debugging browser, dan menelusuri kode. Perhatikan bahwa langkah-langkah yang dijelaskan bergantung pada penggunaan emccalat untuk mengeluarkan WASM. Anda mungkin perlu memodifikasi langkah-langkahnya tergantung pada toolchain khusus Anda.