Rubyから他言語を呼び出す記事が話題となっていますが、今回は「速さ」目的ではなくJavaScriptを呼び出す、ExecJS
gemについて取り上げてみます。
RubyからJavaScriptを呼ぶ場面
Webのフロントエンド側で使える唯一の言語ということで、JavaScriptのポジションに代わるような言語は存在しないのですが、さらにはNode.jsのようなローカル側で実行する環境が整ったこともあって、Web向けのビルドプロセスも多くがJavaScriptで構成されるようになっています。
Railsを使っていても、CoffeeScriptやLESSのコンパイルなど、JavaScriptを使った処理が必要になる場面がちょくちょく発生します。
ExecJSとは?
以上のように、RubyからJavaScriptを実行する必要が生じる場面がいくつかありますが、Ruby自体にJavaScriptの実行機能はもちろんありません。そして、JavaScript環境を作る方法も複数あって、それぞれを組み合わせていては組み合わせ爆発を起こしてしまいます。
ということで、各種のJavaScript環境を抽象化して、同じインターフェースで扱えるようにしているのがExecJS
です。他にも、MultiJSON
のように、「ランタイム抽象化」のためのGemはいろいろ存在しています。
使えるランタイム
ExecJS
で使えるランタイムは、以下のようになっています。
therubyracer
- GoogleのV8をラッピングしたGemです。別プロセスを呼ぶ必要がないので高速で動きます。ただ、JavaScriptの処理系ごと含まれたGemなので、Windowsに入れることが極めて困難なほか、Linux系でもインストールに手間取ることがよくあります。なお、CRubyでLESSを使う場合、依存関係上
therubyracer
が必要となります(LESSではExecJS
を経由しません)。 therubyrhino
- Javaで書かれたRhinoをラップするGemです。JRuby専用です(逆に、JRubyの場合はほぼこれ一択でいいでしょう)。
- Node.js
- コンピューターにインストールされたNode.jsを呼び出します。
- JavaScriptCore
- Mac OS Xに標準で含まれるJavaScriptCoreを呼び出します。
- WSH
- Windows Scripting Host経由でJScriptを実行します。
問題点
上に書いたように、ExecJS
は各種の環境からJavaScriptの実行環境を選ぶので、どんな環境で実行されるかは状況依存となります。とりわけ、WSHのJScriptについてはES5相当の機能すらないために、CoffeeScriptコンパイラが動かないということになっています。
WindowsでもNode.jsを入れてあればそっちが使われるのでこの問題は回避できますが、「Nodeを入れたらRailsのトラブルが解消する」というのも妙なことに思えました。