Play で Scala.js を使う

Play meetup では Play や Scalaフレームワークの歴史みたいな話をしていましたが、本当はこのネタで LT をするつもりでした。諸事情によりってやつです。

さて Play で Scala.js をサポートしようぜって話は少し前からありますが、今のところまだ進展はないようです。

Add buildin ScalaJs support · Issue #2321 · playframework/playframework

ただ、もちろん sbt をいじれば一緒に使うことが可能です。

単純に optimizeJS して出力された js を Play の public/javascripts フォルダにコピーするとか。

lazy val copyJS = Command.command("copyJS") { (state) =>
  scala.sys.process.Process(List("cp", "js/target/scala-2.10/scala-js-slide-js-opt.js", "server/public/javascripts/")).!
  state
}

ちょっとやっつけ感ありますが問題なく使えます。

でもまあもうちょっとまともな方法はが公式サイトからリンク貼られてました。 これを clone するか設定パクればOKです。

git clone git@github.com:vmunier/play-with-scalajs-example.git

このプロジェクトでは Scala.js のプロジェクトが scalajs というサブプロジェクト、Play アプリが scalajvm というサブプロジェクト、さらにその両方で共有されるコードが shared というサブプロジェクトになっています。

├── README.md
├── project
│   ├── Build.scala
│   ├── build.properties
│   ├── plugins.sbt
│   ├── project
│   └── target
├── scala
│   ├── shared
│   └── target
├── scalajs
│   ├── src
│   └── target
└── scalajvm
    ├── app
    ├── conf
    ├── logs
    ├── public
    ├── target
    └── test

このやり方については pab_tech さんも書いてるのでそちらを見てください。

Scala.jsとJVMの両対応コードとScala.jsのテストの書き方 | PABlog

で、Play と使うための build.sbt 設定の中心は以下の部分です。 Scala.js の出力先を Play の public/javascripts にしています。さらに dependsOn を使って Play のアプリをコンパイルしたときに Scala.js のプロジェクトのコンパイルを走らせるようにしています。dist コマンドを使ったときには optimize も行うようになっています。

lazy val scalajvmSettings =
    play.Project.playScalaSettings ++ Seq(
      scalajsOutputDir     := (crossTarget in Compile).value / "classes" / "public" / "javascripts",
      compile in Compile <<= (compile in Compile) dependsOn (preoptimizeJS in (scalajs, Compile)),
      dist <<= dist dependsOn (optimizeJS in (scalajs, Compile)),
    ) ++ (
      // ask scalajs project to put its outputs in scalajsOutputDir
      Seq(packageExternalDepsJS, packageInternalDepsJS, packageExportedProductsJS, preoptimizeJS, optimizeJS) map { packageJSKey =>
        crossTarget in (scalajs, Compile, packageJSKey) := scalajsOutputDir.value
      }
    )

これで、Play でも Scala.js が使えるようになります。やったー!コンパイル時間がさらに伸びますね!

f:id:tototoshi:20140525232911p:plain