Scala.jsが凄い

タイトルで嫌な予感がしてる人もいるでしょうが、ScalaがJSに変換されて動きます。やったぜ。

Scala.js http://www.scala-js.org/

試す

このサンプルプロジェクトを git clone するのが良いです。

sjrd/scala-js-example-app https://github.com/sjrd/scala-js-example-app

サンプルコードはこんな感じ

package example

import scala.scalajs.js
import js.Dynamic.{ global => g }

object ScalaJSExample {
  def main(): Unit = {
    val paragraph = g.document.createElement("p")
    paragraph.innerHTML = "<strong>It works!</strong>"
    g.document.getElementById("playground").appendChild(paragraph)
  }

  /** Computes the square of an integer.
   *  This demonstrates unit testing.
   */
  def square(x: Int): Int = x*x

とりあえずビルドしてみる。

brew install sbt # 何かしらの方法でsbtいれる
git clone sjrd/scala-js-example-app https://github.com/sjrd/scala-js-example-app
cd scala-js-example-app
sbt
sbt pacakgeJS

これで index-dev.htmlを開きます。

It works! Yey!

これとは別に、自分の手元でScalaで書いたライフゲーム、600行ぐらいがそのまま動きました。そのコードは一ヶ月前に紛失したけど一ヶ月前に動いてたのは間違いない。まあとにかくピュアなコードは動く。外部ライブラリは特定のやつだけ動く。そんな感じ。

最適化する

この時点のscala.js、動くことは動くんですが、一つ問題があります。JSが糞でかい!

~/s/scjs2 (master) $ la target/scala-2.10/
total 77488
drwxr-xr-x  9 mizchi  staff   306B  2 14 02:34 .
drwxr-xr-x  6 mizchi  staff   204B  2 14 00:37 ..
drwxr-xr-x  3 mizchi  staff   102B  2 14 00:20 classes
-rw-r--r--  1 mizchi  staff    22M  2 14 00:20 example-extdeps.js
-rw-r--r--  1 mizchi  staff    16M  2 14 00:20 example-extdeps.js.map
-rw-r--r--  1 mizchi  staff     0B  2 14 00:20 example-intdeps.js
-rw-r--r--  1 mizchi  staff   3.1K  2 14 00:20 example.js
-rw-r--r--  1 mizchi  staff   1.4K  2 14 00:20 example.js.map

このexample-extdeps.jsがランタイムコードなんですが、22MBと糞でかい。なぜこんなでかいかというと、JSにコンバートされたScala本体のコードがそのまま入ってます。やばいですね。

たしか僕が最初に試した時(v0.1)はこの解決策がなかったんですが、今のv0.3ではオプティマイザで依存性解析してminifyすることが可能になりました。

$ sbt optimizeJS

(Google Closure Compilerが入ってないといけないかも)

結果。

~/s/scjs2 (master) $ la target/scala-2.10/
total 77488
drwxr-xr-x  9 mizchi  staff   306B  2 14 02:34 .
drwxr-xr-x  6 mizchi  staff   204B  2 14 00:37 ..
drwxr-xr-x  3 mizchi  staff   102B  2 14 00:20 classes
-rw-r--r--  1 mizchi  staff    22M  2 14 00:20 example-extdeps.js
-rw-r--r--  1 mizchi  staff    16M  2 14 00:20 example-extdeps.js.map
-rw-r--r--  1 mizchi  staff     0B  2 14 00:20 example-intdeps.js
-rw-r--r--  1 mizchi  staff   227K  2 14 00:26 example-opt.js
-rw-r--r--  1 mizchi  staff   3.1K  2 14 00:20 example.js
-rw-r--r--  1 mizchi  staff   1.4K  2 14 00:20 example.js.map

example-opt.jsが227KB、まあ許容範囲じゃないでしょうか。問題があるとしたらMacBookPro13インチの最新モデルで最適化に3分ぐらいかかったことですが。

たぶんわざわざscala.jsを導入するようなプロジェクトでは、大量のScalaコードが存在することを前提にするので(じゃなきゃ使う必要ないし)、ガンガンScalaでゲームかなにか書きまくりましょう。Lisperだったらclojurescriptでいいです。

とにかく皆がAltjsの地雷を踏みまくってほしいという願いを込めてこの記事を書きました。現場なら任せろ、俺はあとでいく。