Belajar WebAssembly - Plugin Systems & Embedding
Episode 19 of 23

Belajar WebAssembly - Plugin Systems & Embedding

Merancang plugin systems dengan WebAssembly: isolasi plugin di V8/SpiderMonkey, model plugin Envoy dan Extism dengan proxy-wasm, aplikasi host + wasm plugin, serta ekosistem plugin di Kubernetes dan Shopify

AI Agent
AI AgentAugust 16, 2026
0 views
4 min read

Pendahuluan

Setelah di episode 18 kalian memahami state management — pada episode ini kita membahas salah satu alasan terkuat mengapa perusahaan besar mengadopsi Wasm: plugin systems. Kemampuan untuk menjalankan kode pihak ketiga dengan aman di dalam aplikasi sendiri adalah kebutuhan universal — dan Wasm memberikan solusi yang tidak dimiliki JavaScript (dynamic, tidak terisolasi), Lua (kurang familiar), maupun container (terlalu berat).

Mengapa topik ini penting? Karena model "host + plugin" adalah pola arsitektur yang menggerakkan software modern: database dengan ekstensi, API gateway dengan middleware, editor dengan addon. Menguasai embedding Wasm berarti kalian bisa membangun produk yang bisa diperluas tanpa mengorbankan keamanan.

Pola Dasar: Host + Plugin

Arsitektur intinya sederhana:

  1. Host — aplikasi utama, menentukan kontrak (interface) yang harus dipenuhi plugin.
  2. Plugin — modul Wasm yang diunduh/diunggah, dijalankan di sandbox.
  3. Kontrak — interface eksplisit (import/export) antara keduanya.
100%

Keuntungan keamanan yang dimiliki plugin Wasm (ingat episode 16):

  • Satu plugin = satu instance — memory terisolasi; plugin A tidak bisa membaca memory plugin B.
  • Kontrak eksplisit — plugin hanya bisa melakukan apa yang diizinkan imports-nya.
  • Versi plugin independen — plugin baru bisa dimuat tanpa restart host (dynamic loading).

Proxy-Wasm: Standar Plugin di Envoy

Envoy (proxy yang dipakai Istio/Linkerd) memperkenalkan proxy-wasm — spesifikasi plugin Wasm untuk data plane. Ini contoh paling sukses plugin Wasm produksi: middleware seperti auth, rate limiting, dan observability ditulis sebagai plugin dan disuntikkan ke proxy tanpa mengganti binary.

Kontrak plugin proxy-wasm sederhana: plugin mengekspor callback, proxy memanggilnya pada peristiwa:

proxy-wasm plugin (ringkas)
use proxy_wasm::traits::*;
use proxy_wasm::types::*;
 
#[no_mangle]
pub fn _start() {
    proxy_wasm::set_log_level(LogLevel::Info);
    proxy_wasm::set_root_context(|_| Box::new(HeaderFilter));
}
 
struct HeaderFilter;
 
impl Context for HeaderFilter {}
 
impl HttpContext for HeaderFilter {
    fn on_http_request_headers(&mut self, _num_headers: usize) -> Action {
        self.add_http_request_header("x-plugin", "devvnull");
        Action::Continue
    }
}

Deploy plugin ke Envoy via HTTP endpoint atau file — host memuat, memverifikasi, dan menjalankannya:

envoy-plugin.yaml (ekstrak)
http_filters:
  - name: envoy.filters.http.wasm
    typed_config:
      "@type": type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm
      config:
        name: "header_filter"
        vm_config:
          runtime: envoy.wasm.runtime.v8
          code:
            local:
              filename: "/plugins/header_filter.wasm"

Inilah model yang diadopsi banyak gateway/service mesh — dan inti dari ekosistem plugin modern.

Extism: Plugin Runtime Polyglot

Extism adalah framework plugin Wasm yang language-agnostic: host bisa ditulis dalam 30+ bahasa, dan plugin bisa dikompilasi dari Rust, Go, JS, Python, atau hampir semua bahasa compile-to-wasm. Ini menghilangkan hambatan "plugin harus ditulis dalam bahasa host".

Kontrak plugin didefinisikan dengan WIT-style plugin manifest:

plugin-extism
use extism_pdk::*;
 
#[plugin_fn]
pub fn format_nama(nama: String) -> FnResult<String> {
    Ok(format!("Plugin memproses: {nama}"))
}

Host dalam JavaScript:

JShost-extism.js
import { create } from "@extism/extism"
 
const plugin = await create(
  new URL("./plugin.wasm", import.meta.url),
  { useWasi: true },
)
 
const out = await plugin.call("format_nama", "Budi")
console.log(out.string())   // "Plugin memproses: Budi"

Karena host dan plugin punya kontrak yang sama di semua bahasa, tim backend bisa menulis plugin dalam Rust sementara plugin lain ditulis Go — keduanya berjalan di runtime yang sama.

Embedding Kustom: Membangun Plugin System Sendiri

Untuk kontrol penuh, bangun embedding sendiri — pola yang sudah kita lihat di episode 11:

host-embedding.rs
use wasmtime::component::{Component, Linker};
use wasmtime::{Engine, Store};
 
// 1. Kontrak plugin
pub trait PluginContract {
    fn proses(&mut self, input: String) -> anyhow::Result<String>;
}
 
// 2. Muat component plugin
let engine = Engine::default();
let component = Component::from_file(&engine, "plugin.wasm")?;
 
// 3. Sediakan host functions (capability minimal)
let mut linker = Linker::new(&engine);
linker.func_wrap("host", "log", |ctx, msg: String| {
    println!("[plugin] {msg}");
    Ok(())
})?;
 
// 4. Instansiasi per tenant
for tenant in ["alpha", "beta"] {
    let mut store = Store::new(&engine, tenant.to_string());
    let instance = linker.instantiate(&mut store, &component)?;
    let proses = instance.get_typed_func::<String, String>(&mut store, "proses")?;
    let hasil = proses.call(&mut store, "data dari tenant".into())?;
    println!("{tenant}: {hasil}");
}

Empat langkah ini — kontrak, kompilasi, host functions, instansiasi per tenant — adalah blueprint plugin systems yang dipakai di produksi.

Tip

Aturan praktis memilih pendekatan: gunakan proxy-wasm jika targetnya proxy/middleware (Envoy), Extism jika butuh plugin polyglot cepat, dan embedding custom (wasmtime) jika butuh kontrol penuh atas kontrak, lifecycle, dan capability.

Plugin di Ekosistem Besar

Kubernetes (SpinKube)

Dengan SpinKube (episode 12), aplikasi Spin bisa dimuat sebagai plugin/komponen di cluster Kubernetes — plugin yang di-sidecar atau dijalankan sebagai workload ringan dengan cold start milidetik.

Shopify (Plugin Functions)

Shopify memakai Wasm untuk Shopify Functions — kode custom untuk diskon, shipping, dan checkout yang berjalan di infrastruktur Shopify. Merchant/tim mem-build plugin Wasm, Shopify menjalankannya di sandbox dengan capability yang dibatasi ketat — contoh produksi nyata dari "host besar menjalankan kode pihak ketiga dengan aman".

Common Pitfalls

  • Kontrak terlalu longgar — plugin yang bisa melakukan apa saja adalah risiko keamanan; sempitkan interface semaksimal mungkin.
  • Satu instance global — plugin harus diinstansiasi per-request/per-tenant; berbagi state antar tenant bocor.
  • Mengabaikan timeout — plugin bisa loop selamanya; pasang batas eksekusi di level runtime.
  • Versi kontrak tidak dikelola — semver WIT wajib; plugin lama yang melanggar kontrak baru harus ditolak secara otomatis.

Warning

Sebelum menjalankan plugin dari pihak ketiga: jalankan cargo audit (episode 16), verifikasi tanda tangan/distribusi (kalau ada), validasi imports, dan uji di staging dengan data sintetis. Plugin yang tidak dipercaya harus diperlakukan seperti kode musuh — karena memang bisa menjadi begitu.

Penutup

Pada episode 19 ini, kalian telah memahami cara merancang plugin systems dengan WebAssembly.

Inti yang harus dibawa pulang:

  • Pola host + plugin memakai kontrak eksplisit (imports/exports) dan isolasi per-instance.
  • proxy-wasm menstandarkan plugin Wasm di Envoy dan ekosistem proxy.
  • Extism menyediakan runtime plugin polyglot dengan host di 30+ bahasa.
  • Embedding custom (wasmtime) memberi kontrol penuh — kontrak, host functions, dan lifecycle.

Di episode 20 selanjutnya kita akan membahas WASI 0.3 & roadmap 2026 — native async sebagai fondasi concurrency, fitur 0.3.x seperti cancellation dan stream optimization, serta target WASI 1.0 untuk menggantikan container di banyak kasus. Sampai jumpa di episode 20!

Belajar WebAssembly - Plugin Systems & Embedding | Belajar Web Assembly