← Articoli

jsg: un piccolo aiuto per i progetti ruby.wasm

ruby.wasm esegue CRuby nel browser, e la gem js fa da ponte tra il vostro codice Ruby e il mondo JavaScript. Avviare un progetto richiede però ancora alcuni passi manuali: una pagina HTML, lo script per il browser, un Gemfile, un comando di build e un web server locale.

Nel 2024 ho raccolto questi passi in una piccola gem chiamata jsg. Il suo gemspec la riassume in una riga: “JSG helps setting up ruby.wasm projects and comes with a nicer syntax”. Le metà sono quindi due: uno strumento da riga di comando che prepara e compila un progetto, e un file Ruby che caricate nel browser.

Un avvertimento onesto: jsg è un esperimento in fase iniziale. La versione attuale è la 0.1.2 del maggio 2024, il README su GitHub è ancora il segnaposto di Bundler e non esiste ancora una vera suite di test. Questo articolo è quanto di più vicino a una documentazione esista.

Installazione

jsg richiede Ruby 3.0 o successivo e dipende dalla gem js (~> 2.6) e da erb:

gem install jsg

Lo strumento da riga di comando

La gem include un eseguibile jsg con tre comandi:

jsg new myapp   # create a project from the template, then build it
jsg build       # bundle install, then build assets/ruby-app.wasm
jsg server      # serve the current directory with WEBrick

jsg new myapp copia il template in una nuova cartella myapp. Ottenete:

Subito dopo la copia entra nella cartella ed esegue la build. jsg build fa esattamente due cose: bundle install e rbwasm build -o assets/ruby-app.wasm. Il commento in src/main.rb del template spiega l’idea: il vostro codice va lì e, dopo jsg build, finisce all’interno del file .wasm.

jsg server (o jsg serve) avvia WEBrick sulla porta 8080 e passa alla porta successiva se la 8080 è già occupata. La cartella degli esempi usa invece il one-liner integrato in Ruby, che funziona altrettanto bene:

ruby -run -e httpd . -p 8080

Entrambi si basano su WEBrick, che da Ruby 3.0 non fa più parte della libreria standard; potrebbe quindi servire prima un gem install webrick.

La “sintassi più comoda”

La seconda metà è jsg.rb. Definisce un modulo JSG con alcune scorciatoie e aggiunge una serie di metodi a JS::Object. Questo è il Ruby eseguito dalla pagina di esempio nel repository:

require 'jsg'

$window = JSG.global
$d = $window.document

$d.getElementById("spinner").style.display = "none"

$d.createElement("h2").tap {|e|
    e.innerText = "Examples"
    $d.body.appendChild(e)
}

Invece di JS.global[:document] scrivete $window.document, e chiamate i metodi del DOM come fareste in JavaScript. Ecco cosa aggiunge il sorgente:

L’index.html del template mostra anche un trucco per lo sviluppo: ridefinisce require_relative per caricare i file via HTTP tramite JS::RequireRemote. Il commento spiega che serve solo se volete usare require_relative invece di jsg build.

Stato

jsg è piccola e ancora un po’ grezza. Se la provate e qualcosa non funziona, il sorgente è breve: un file Ruby per il lato browser e uno script in exe/jsg. Issue e pull request sono benvenute su GitHub. La licenza è MIT.

ruby.wasm compare anche in un altro mio progetto: il port di Hackety Hack dietro clogs ha una build per browser che esegue CRuby compilato in WebAssembly.