Opal is a Ruby to JavaScript source-to-source compiler, shipping with an implementation of the Ruby corelib and stdlib.
Write Ruby, run it anywhere JavaScript runs — the browser, Node.js, Deno, Bun, QuickJS.
- A real Ruby implementation. Opal ships its own corelib and stdlib and is validated against ruby/spec, the same suite CRuby uses. A JavaScript host imposes limits — those are catalogued in Unsupported Features.
- Source-to-source, no runtime interpreter. Ruby compiles to plain JavaScript ahead of time, so there is no VM to download and no interpreter loop at runtime.
- Two-way JavaScript interop. Call JS from Ruby and Ruby from JS, and treat native JS classes as Ruby ones. See Interfacing with JavaScript.
- Share code between server and client. The same gem, the same objects, the same specs, on both sides of the wire.
- It compiles itself. The compiler is written in Ruby and builds to
opal-parser.js, so it also runs inside the browser.
Opal needs Ruby. The gemspec declares >= 2.3; CI exercises Ruby 3.0 through 4.0
and JRuby, so 3.x or newer is the sensible choice.
gem install opalOr in your Gemfile:
gem 'opal'This installs the latest release, from the 1.8 series. The master branch is
2.0.0dev and is not yet released; to track it:
gem 'opal', github: 'opal/opal'Then check it:
opal -v
opal -e "puts 'Hello from Opal'"The second command prints Hello from Opal — it compiled the Ruby and ran the
result on Node.js.
- Guides — tutorial, how-to guides, reference, and explanation, also rendered at opalrb.com/docs.
- Getting Started — the tutorial to follow first.
- Migrating to Opal 2.0 — every breaking change from 1.x, with old and new code side by side.
- CLI Reference and Runners — every flag and every execution target.
- Framework integrations: Rails, Sinatra, Roda, static apps.
Contents of app.rb:
puts 'Hello world!'Then from the terminal:
opal --compile app.rb > app.jsThe Opal runtime is included by default; skip it with --no-opal.
The resulting JavaScript file runs from an HTML page. Set the page encoding to
UTF-8 — Opal's string handling depends on it:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="app.js"></script>
</head>
<body>
</body>
</html>Open the page in a browser and check the JavaScript console.
Opal.compile compiles a string of Ruby into a string of JavaScript:
require 'opal'
Opal.compile("puts 'wow'")
# => "Opal.queue(function(Opal) { ... return self.$puts(\"wow\") ... });\n"That output alone is not runnable — it needs the Opal runtime/corelib.
Opal::Builder builds the runtime:
Opal::Builder.build('opal') # => "(function() { ... })()"or an entire app, resolving require dependencies:
builder = Opal::Builder.new
builder.build_str('require "opal"; puts "wow"', '(inline)')
File.binwrite 'app.js', builder.to_s # must use binary mode for writingopal-parser evaluates Ruby directly from your HTML files, with no build step:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="https://cdn.opalrb.com/opal/current/opal.js"></script>
<script src="https://cdn.opalrb.com/opal/current/opal-parser.js" onload="Opal.load('opal-parser')"></script>
<script type="text/ruby">
puts "hi"
</script>
</head>
<body>
</body>
</html>Open the page and check the JavaScript console.
NOTE: this ships the compiler to the client. It is a fast way to try Opal, not a way to deploy it.
The upcoming 2.0 targets ES2021: compiled output and the Opal runtime assume an ES2021-capable engine, and there is no transpilation fallback. If you need to support an older engine, stay on Opal 1.x. See the migration guide for the full rationale.
That means:
- Firefox, Chrome, Safari, Edge — current and previous stable versions
- Node.js, Deno, Bun, QuickJS, and more — see Runners
Internet Explorer is not supported. Problems on any engine listed above should be reported as bugs.
HACKING.md is the contributor guide — prerequisites, bin/setup, running the
spec suites, benchmarking, and profiling:
- HACKING.md — development environment and test suites
- CONTRIBUTING.md — how to file issues and open pull requests
The short version, once you have cloned the repo:
bin/setup
bundle exec rakelib/— the Opal parser and compiler. Runs in your Ruby environment, and is also built for the browser asopal-parser.js.opal/— the runtime and corelib, written in Ruby and JavaScript. Runs in the JavaScript environment.stdlib/— Opal's implementation of Ruby's stdlib (StringScanner,Date,Observable, …). Optional, runs in the JavaScript environment.
Opal will broadly follow semver as a version policy, trying to bump the major version when introducing breaking changes. Being a language implementation we're also aware that there's a fine line between what can be considered breaking and what is expected to be "safe" or just "additive". Moving forward we'll attempt to better clarify what interfaces are meant to be public and what should be considered private.
The master branch is currently 2.0.0dev — unreleased. The latest released gem
is on RubyGems.
- Slack — chat with maintainers and users
- Stack Overflow
#opalrb— questions - Issues — bugs and feature requests
This project exists thanks to all the people who contribute.
Thank you to all our backers! 🙏 [Become a backer]
Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [Become a sponsor]
Opal is released under the MIT License. See LICENSE for the full text.