Skip to content

Latest commit

 

History

History
98 lines (65 loc) · 6.1 KB

README.md

File metadata and controls

98 lines (65 loc) · 6.1 KB

Ruby.wasm quickstart

For the rest of us

ruby.wasm runs the Ruby programming language in the browser using WebAssembly. This project is a set of small examples that you can copy. It comes with a prebuilt assets/ruby-app.wasm that contains Ruby 4.0, the JavaScript bridge (the js gem), jsg and kramdown, so you can start without compiling anything.

The examples use jsg, which gives the js gem a friendlier syntax:

require "jsg"

d = JSG.document
d.getElementById("spinner").style.display = "none"   # instead of JS.global[:document].getElementById("spinner")[:style][:display] = "none"
d.querySelectorAll("li").each { |li| li.classList.add("done") }

Examples

Run it locally

Works the same on Linux, macOS and Windows: you need Ruby 3.3 or newer (on Windows RubyInstaller with the Devkit).

gem install jsg webrick
git clone https://github.com/Largo/ruby.wasm-quickstart.git
cd ruby.wasm-quickstart
jsg server        # http://localhost:8080

Any static web server works, for example ruby -run -e httpd . -p 8080. Opening the HTML files directly from disk does not work, because the browser has to fetch the .wasm file.

Add gems

Gems from the Gemfile are packed into assets/ruby-app.wasm, so after changing the Gemfile you rebuild it. You only need this for gems: your own Ruby files are loaded from the web server (see below).

Linux and macOS (needs a C compiler, make and curl; on macOS the Xcode Command Line Tools and brew install openssl@3, because the Ruby that rbwasm builds for the host does not compile against OpenSSL 4 yet):

./build.sh

Windows: rbwasm cannot build natively on Windows, so build in Docker (Docker Desktop). This also works on Linux and macOS if you don't want to install a toolchain:

docker build -t ruby-wasm-quickstart .
docker run --rm -v "${PWD}:/app" ruby-wasm-quickstart

(In bash or zsh write "$PWD:/app".) Inside WSL, ./build.sh works like on Linux.

build.sh runs jsg build, which does bundle install and rbwasm build --ruby-version 4.0 -o assets/ruby-app.wasm, and then strips the debug info (51 MB → 33 MB). The first build compiles CRuby and the gems for WebAssembly and takes a while. Later builds reuse the build/ and rubies/ folders. Delete them when you switch between a Docker and a native build. Gems with C extensions need a WebAssembly build of the extension, so pure Ruby gems are the easy case.

Note: if your own Ruby 4.0 is installed with the prefix /usr/local (for example the official ruby Docker images), the native build currently fails with 'ruby/config.h' file not found, because rbwasm's WebAssembly Ruby uses the same prefix. Use the Docker image from this repository or a Ruby from a version manager or Homebrew instead.

Tests

node test/pages.test.js http://127.0.0.1:8080/ opens every example in Chromium (Playwright, npm install playwright) and checks that the Ruby code ran. GitHub Actions runs it on Linux, macOS and Windows, and builds the wasm file natively on Linux and macOS and in Docker.

Your own Ruby files

Your own code does not have to be inside the wasm file. There are three ways to load it:

  • inline: <script type="text/ruby"> ... </script> (see canvas.html)
  • one file: <script type="text/ruby" src="runCode.rb" data-eval="async"></script> (see run-code.html)
  • several files: JS::RequireRemote fetches files from the web server, and with require "js/require_remote/relative_shim" a plain require_relative works, relative to the file that calls it (see require.html)

The files are loaded from the server on every page load, so a reload picks up your changes without a rebuild.

data-eval="async" runs the script so that .await works in it, e.g. JSG.window.fetch("README.md").await.

Start a new project

jsg new myapp creates a fresh project with the same layout (index.html, src/main.rb, assets/, Gemfile) and builds it.

References

GPT to convert JavaScript to Ruby code

ChatGPT – Ruby.wasm JavaScript Helper