- WebAssembly telah berkembang sejak rilis pertamanya pada 2017 dengan mendukung eksekusi bahasa tingkat rendah seperti C/C++, tetapi hingga kini masih diperlakukan sebagai bahasa kelas dua di platform web
- Hanya JavaScript yang dapat berinteraksi langsung dengan Web API, sedangkan WebAssembly harus menulis kode binding JS yang kompleks (glue code) untuk melakukannya
- Struktur ini menyebabkan prosedur pemuatan yang rumit, overhead performa, dan terputusnya toolchain antarbahasa, sehingga menurunkan pengalaman developer
- Untuk mengatasinya, Mozilla mengusulkan WebAssembly Component Model, yang memungkinkan pemanggilan Web API dan pemuatan modul secara terstandarisasi tanpa JS
- Jika model ini mapan, WebAssembly diperkirakan akan menjadi lingkungan eksekusi kelas satu di browser, membuka jalan agar developer umum pun bisa memanfaatkannya dengan mudah
Mengapa WebAssembly diperlakukan sebagai bahasa kelas dua
- WebAssembly hanya bisa mengakses platform web melalui JavaScript, dan tidak memiliki izin untuk memanggil Web API secara langsung
- JavaScript dapat dimuat dengan sederhana lewat tag
<script>, tetapi WebAssembly memerlukan proses pemuatan manual melalui JS API
- Harus melewati pemanggilan API yang kompleks seperti
WebAssembly.instantiateStreaming(), sehingga developer perlu menghafalnya atau mengandalkan otomatisasi dari tool
- Proposal esm-integration menyederhanakan prosedur pemuatan dengan memungkinkan file
.wasm di-import langsung melalui sistem modul JS
- Dapat dimuat langsung dalam bentuk
<script type="module" src="/module.wasm"></script>
Keterbatasan akses ke Web API
- Di JavaScript, pekerjaan yang cukup dilakukan dengan satu baris
console.log("hello, world") di WebAssembly memerlukan prosedur rumit seperti akses memori JS, decoding string, dan wrapping fungsi
- Karena WebAssembly tidak dapat mengakses objek
console atau DOM, ia harus melakukan pemanggilan tidak langsung lewat berbagi memori serta import/export fungsi di JS
- Binding code (glue code) yang dihasilkan dalam proses ini berbeda untuk tiap bahasa, dan biasanya dibuat otomatis dengan tool seperti
embind atau wasm-bindgen
- Namun, ini menimbulkan masalah seperti build yang makin kompleks, runtime overhead, dan inkompatibilitas antarbahasa
Penyebab teknis WebAssembly belum menjadi bahasa kelas satu
- Sulitnya integrasi compiler: compiler tiap bahasa harus menghasilkan kode integrasi JS dan platform web secara terpisah, dan hasilnya tidak bisa digunakan ulang
- Inkompatibilitas compiler standar: file yang dihasilkan dengan
rustc --target=wasm tidak bisa langsung dijalankan di browser
- Diperlukan instalasi toolchain tidak resmi terpisah yang mengimplementasikan integrasi platform
- Bias dalam ekosistem dokumentasi: dokumentasi web seperti MDN sebagian besar ditulis berpusat pada JavaScript, sehingga hambatan masuknya tinggi bagi pengguna bahasa lain
- Masalah performa: pemanggilan DOM yang melewati binding JS mengalami penurunan performa 45% dibanding pemanggilan langsung
- Dalam eksperimen framework Dodrio, waktu penerapan perubahan DOM turun menjadi setengah setelah JS glue dihapus
- Ketergantungan pada JavaScript: untuk memakai WebAssembly dalam praktik kerja nyata, pada akhirnya developer tetap harus memahami JS, yang berujung pada masalah leaky abstraction
Munculnya WebAssembly Component Model
- WebAssembly Component Model mendefinisikan unit eksekusi terstandarisasi yang bisa dipakai bersama di berbagai bahasa dan runtime
- Akses Web API, pemuatan modul, dan proses linking dapat dilakukan langsung tanpa JS
- Dapat dihasilkan dari berbagai bahasa dan didukung untuk dijalankan di browser maupun runtime lain seperti Wasmtime
- Melalui WIT (Interface Description Language), API yang dibutuhkan dapat dideklarasikan dan kemudian dipanggil langsung dari dalam komponen
- Browser dapat memuat komponen secara langsung dengan
<script type="module" src="component.wasm"></script>, dan secara otomatis menangani binding Web API tanpa JS
Interoperabilitas dengan JavaScript
- Component Model juga mendukung struktur aplikasi hibrida
- Contoh: decoder gambar ditulis dalam WebAssembly, lalu dipanggil dari JS dalam bentuk
import { Image } from "image-lib.wasm";
- JS dapat menggunakan komponen WebAssembly dengan import/export seperti modul biasa
Prospek ke depan dan partisipasi
- Mozilla sedang mengerjakan standardisasi Component Model bersama WebAssembly CG, dan Google juga masih dalam tahap peninjauan
- Developer dapat bereksperimen lewat Jco atau Wasmtime di browser maupun CLI
- Jika model ini mapan, WebAssembly berpotensi berkembang dari fitur untuk power user menjadi teknologi web yang juga mudah dimanfaatkan developer umum
4 komentar
Ini rasanya cuma mendekati angan-angan ala Mozilla. Frontend secara struktural tidak bisa lepas dari sistem limbik reaksi pasar. Begitu WebAssembly muncul, Doom 3 langsung di-port. DOM di browser modern sudah lama berubah menjadi objek proksi ringan, dan jika mempertimbangkan set instruksi khusus JavaScript pada CPU modern serta batas kuantum single-core, pendekatan seperti ini tidak akan pernah memperoleh keunggulan dari sisi nilai pasar.
Apa arti biner WebAssembly yang berjalan di dalam Electron? Ini cuma terlihat seperti GitKraken CLI versi lain, atau semacam perburuan gengsi porting Rust.
Kalau yang lain sih entahlah, tapi cara menyisipkan modul wasm sebagai file seperti
<script type="module" src="/module.wasm"></script>ini cukup menggoda.Dan saya rasa saya harus mengatakan dengan tegas bahwa klaim-klaim bahwa hambatan masuk WebAssembly itu tinggi adalah omong kosong. Hanya saja kebutuhannya memang lebih rendah daripada kemauan untuk membayar. Ingin cepat dan footprint rendah sambil tetap memakai DOM dan CSS? Ini komedi gelap macam apa.
Komentar Hacker News
Cukup disayangkan bahwa saat target awal untuk mendukung WebIDL di WebAssembly ditinggalkan dan diputuskan membuat IDL lain, absennya akses DOM tidak dianggap sebagai masalah
Tentu saya paham realitas pasar, tetapi tetap sulit menghilangkan rasa sayang pada waktu yang terbuang
Referensi terkait: riwayat commit, retrospektif stringref, artikel ACM
Setelah itu ada dua target tambahan, yaitu dukungan API non-web dan interoperabilitas antarbahasa
WebIDL adalah gabungan JS dan Web API, jadi daya ekspresinya tinggi, tetapi banyak konsep di dalamnya yang bentrok dengan target-target ini
Karena itu component interface memilih pendekatan irisan yang jauh lebih portabel, meski dengan daya ekspresi yang lebih rendah
Secara pribadi saya menganggap akses DOM penting, tetapi Wasm CG sibuk dengan hal-hal lain yang prioritasnya lebih tinggi
Alasan saya menulis artikel ini adalah untuk memberi tahu bahwa masalah ini masih saya ingat dan saya berniat terus mengerjakannya
Toolchain dan proses build terlalu rumit, jadi setiap kali memakainya saya merasa ada beban kognitif yang besar
Performanya jauh lebih baik tanpa glue, tetapi risiko yang menyertainya juga besar
Saya berharap component model tidak memperkenalkan kompleksitas baru, tetapi melihat contoh dari berbagai bahasa, situasinya sudah cukup membingungkan
Terutama jika melihat contoh Go, file yang dihasilkan terlalu banyak, dan dari sudut pandang pengembang, penyederhanaan tooling sangat dibutuhkan
Sekarang ini terlihat bukan menghilangkan kompleksitas, melainkan hanya memindahkannya
Spesifikasi wasm component terus berubah sehingga banyak churn
Tujuannya adalah agar pengembang web tidak perlu menulis WIT secara langsung, dan bisa memakai Web API seperti library
Namun jalannya masih panjang
Misalnya dibagi menjadi berbagi teks, berbagi media, berbagi aplikasi, dan seterusnya; ini akan meningkatkan keamanan sekaligus memungkinkan tim kecil membuat alternatif browser
Tetapi skala Web API yang sangat besar dan CSS adalah faktor yang menopang monopoli browser, jadi upaya seperti itu tampaknya sulit
Akan bagus jika WebAssembly registry distandardisasi agar komponen bisa digabungkan dengan mudah
Pada akhirnya web adalah proses membangun definisi sistem operasi terdistribusi
Dari konsep sampai contoh kode, semuanya tertata dengan baik
Di ekosistem JS, tiga proyek kuncinya adalah StarlingMonkey, ComponentizeJS, dan jco
Saat ini toolchain yang paling matang adalah Rust, tetapi dukungan untuk bahasa berbasis LLVM (C/C++, Go, Python, dan lain-lain) juga terus membaik
Tujuan WebAssembly adalah menjadi target kompilasi yang menyatu secara alami dengan toolchain lokal
Jika masih harus memahami glue code khusus bahasa atau dua model runtime yang berbeda, WebAssembly akan tetap menjadi “alat yang hanya dipakai dalam situasi ekstrem”
Untuk benar-benar membawa perubahan, jalur build umum harus disederhanakan
Tidak jelas bagaimana bagian ini ditangani dalam Component Model
DOM berbeda di setiap browser, dan fitur bisa berubah setiap kali halaman dimuat
Di lapisan bridge JS, polyfill bisa diterapkan dengan mudah, tetapi pada antarmuka WIT, deteksi method saat runtime maupun polyfill terasa sulit
Selain performa, fleksibilitas ekosistem juga penting
Harus mengelola glue code JS sendiri atau bergantung pada alat pembangkit otomatis terasa seperti kemunduran besar
Dalam eksperimen Dodrio, menghilangkan glue menghasilkan penurunan overhead 45%, dan itu mengesankan
Namun saya penasaran bagaimana manajemen memori bekerja saat WebAssembly Component Model berinteraksi langsung dengan Web API
Apakah proposal Wasm GC dipakai untuk mempertahankan referensi DOM, atau masih bergantung pada JS GC
Saya berharap Wasm benar-benar bisa menjadi warga kelas satu
Tetapi saat ini IPC masih tidak efisien, dan saya rasa dibutuhkan pendekatan seperti transfer berbasis halaman memori
Membiarkan siapa pun menjalankan program kompleks di komputer saya terdengar seperti ide keamanan yang gila, tetapi memang itulah yang kita lakukan
Berkat JS, selama 20 tahun kita mengalami banyak bug keamanan browser, tetapi sekarang prinsip desain dan langkah mitigasinya sudah lebih mapan
Lalu ironis sekaligus indah bahwa sekarang kita mencoba menggantinya lagi dengan paradigma eksekusi berisiko yang lain
OS mobile melakukannya jauh lebih baik daripada desktop
Semuanya dirancang dari sudut pandang engineer, dan tidak ada workflow default yang ramah author
Meski begitu, saya bersyukur masih ada orang-orang yang peduli pada masalah ini
Rasanya seperti rekayasa berlebihan demi pemrosesan string yang 2x lebih cepat hanya untuk memetakan DOM API secara 1:1
Pada API seperti WebGL2, WebGPU, dan WebAudio, biaya JS shim sudah nyaris tak berarti
Masalah sebenarnya ada pada hal-hal seperti penyalinan buffer GPU, dan component model tidak membantu di sana
Saya ingin melihat benchmark yang menguji puluhan ribu draw call di WebGL2 atau WebGPU
Selain performa, peningkatan pengalaman pengembang (DX) juga penting
Saat ini terlalu sulit untuk memulai, dan semua orang harus menjadi ahli dulu baru bisa mendapatkan manfaatnya
Jika bisa bersaing dengan efisiensi setingkat aplikasi native, itu adalah perubahan visioner untuk masa depan web
Di era coding agent, peningkatan DX yang mereka bicarakan itu rasanya tidak lagi penting