← Blog

jsg: ruby.wasmプロジェクトのための小さなヘルパー

ruby.wasmを使うと、ブラウザの中でCRubyを動かせます。RubyのコードとJavaScriptの世界をつなぐのはjs gemです。ただ、プロジェクトを始めるまでには、HTMLページ、ブラウザ用スクリプト、Gemfile、ビルドコマンド、ローカルのWebサーバーと、手作業がいくつか必要になります。

2024年に、この手順をjsgという小さなgemにまとめました。gemspecの説明は一文だけで、「ruby.wasmプロジェクトのセットアップを助け、より書きやすい構文を提供する」というものです。つまり中身は二つあります。プロジェクトを作ってビルドするコマンドラインツールと、ブラウザで読み込むRubyファイルです。

最初に正直にお伝えしておくと、jsgはまだ初期の実験段階です。現在のバージョンは2024年5月の0.1.2で、GitHubのREADMEはBundlerが生成したひな形のままですし、ちゃんとしたテストもまだありません。今のところ、この記事がいちばんドキュメントに近いものです。

インストール

Ruby 3.0以降が必要で、js gem(~> 2.6)とerbに依存しています。

gem install jsg

コマンドラインツール

gemにはjsgコマンドが含まれていて、サブコマンドは三つです。

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を実行すると、テンプレートが新しいmyappフォルダにコピーされます。中身は次のとおりです。

コピーが終わると、そのフォルダに移動してそのままビルドを実行します。jsg buildがやることは二つだけで、bundle installとrbwasm build -o assets/ruby-app.wasmです。テンプレートのsrc/main.rbのコメントにあるとおり、自分のコードはここに書き、jsg buildのあとで.wasmファイルの中に入ります。

jsg server(またはjsg serve)はWEBrickをポート8080で起動し、8080が使用中なら次のポートを試します。examplesフォルダではRuby組み込みのワンライナーを使っていて、こちらでも同じように動きます。

ruby -run -e httpd . -p 8080

どちらもWEBrickを使いますが、WEBrickはRuby 3.0から標準ライブラリに含まれなくなりました。先にgem install webrickが必要になるかもしれません。

「書きやすい構文」

もう一つの部分がjsg.rbです。いくつかのショートカットを持つJSGモジュールを定義し、JS::Objectにメソッドを追加します。リポジトリのサンプルページで実行しているRubyコードはこちらです。

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)
}

JS.global[:document]と書く代わりに$window.documentと書けて、DOMのメソッドもJavaScriptと同じ感覚で呼び出せます。ソースコードで追加されている機能は次のとおりです。

テンプレートのindex.htmlには開発用の工夫もあります。require_relativeを再定義して、JS::RequireRemote経由でファイルをHTTPで読み込むようにしています。コメントによると、これはjsg buildではなくrequire_relativeを使いたい場合にだけ必要なものです。

現状

jsgは小さく、まだ荒削りなところがあります。試してみてうまく動かないところがあっても、ソースは短く、ブラウザ側のRubyファイルが一つとexe/jsgのスクリプトが一つだけです。IssueやPull RequestはGitHubでお待ちしています。ライセンスはMITです。

ruby.wasmは私の別のプロジェクトにも登場します。clogsを使ったHackety Hackの移植には、WebAssemblyにコンパイルしたCRubyで動くブラウザ版があります。