Play Frameworkとsbtを使っていて、sbt runを実行した時にどういうことが起こっているのか、compileしたときのmain関数はどこにあるのかあたりが分かってなかった。この辺が分かってないと、開発でrunしている最中に変な挙動をした場合のデバッグや、本番アプリケーションサーバのチューニングなどがしづらい。そこで今回はPlay Frameworkのサーバ立ち上げ部分のコードを追いかけてみたのでメモ。あんまりsbtに詳しくないので、内容が間違っていたら教えてください。
playframeworkを使っているプロジェクトでbuild.sbtに書いていること
build.sbt書いている内容はこれだけ。
lazy val root = (project in file(".")).enablePlugins(PlayScala)
またproject/plugins.sbtには以下が書かれている。
addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.6.13")
これだけでrunやcompileがうまく動くようになってて不思議。
addSbtPluginでPlayScalaが使えるようになる
- https://github.com/playframework/playframework/blob/aa66958fa46b573bbf7cd8b92a92568c64c15cd4/framework/src/sbt-plugin/src/main/scala/play/sbt/Play.scala#L84..L95
- https://github.com/playframework/playframework/blob/aa66958fa46b573bbf7cd8b92a92568c64c15cd4/framework/src/sbt-plugin/src/main/scala/play/sbt/Play.scala#L33..L48
この辺?これでenablePluginsができるようになるはず。
sbt runで立ち上がるもの
まずsbtでinspect runするとどこで定義されているか分かる。PlaySettingsにありそう。
[play-scala-slick-example] $ inspect run ... [info] Defined at: [info] (play.sbt.PlaySettings.serviceSettings) PlaySettings.scala:105 ...
https://github.com/playframework/playframework/blob/aa66958fa46b573bbf7cd8b92a92568c64c15cd4/framework/src/sbt-plugin/src/main/scala/play/sbt/PlaySettings.scala#L104..L106 あたりで、runしたときはPlayRun.playDefaultRunTaskを呼ぶようになってて、Compile/run/mainClassにplay.core.server.DevServerStartを設定している。
https://github.com/playframework/playframework/blob/aa66958fa46b573bbf7cd8b92a92568c64c15cd4/framework/src/sbt-plugin/src/main/scala/play/sbt/run/PlayRun.scala#L79..L96 devModeServerの定義で先程のmainClassを使いつつ、Reloaderを使ってサーバを起動できるようにする。
https://github.com/playframework/playframework/blob/aa66958fa46b573bbf7cd8b92a92568c64c15cd4/framework/src/run-support/src/main/scala/play/runsupport/Reloader.scala#L226..L235 portの設定有無によって、先程渡したmainClassのmainDevHttpModeとかを使って立ち上げる。つまりデフォルトではplay.core.server.DevServerStart.mainDevHttpModeかな。
https://github.com/playframework/playframework/blob/aa66958fa46b573bbf7cd8b92a92568c64c15cd4/framework/src/play-server/src/main/scala/play/core/server/DevServerStart.scala#L52..L58 あとはこのへんで頑張ってサーバを起動してますね。
こんな感じの流れっぽい。
compileやdistしたときのmain関数はどこか
sbt runは開発サーバが起動したが、compileした時は違うはず。調べてみるとこちらもPlaySettingsにかかれていた。
https://github.com/playframework/playframework/blob/aa66958fa46b573bbf7cd8b92a92568c64c15cd4/framework/src/sbt-plugin/src/main/scala/play/sbt/PlaySettings.scala#L152..L153 Compile/mainClassにplay.core.server.ProdServerStartが設定されている。
こういう感じなので、https://www.playframework.com/documentation/aa66958fa46b573bbf7cd8b92a92568c64c15cd4/Deploying にかかれているようにdistやuniversal:packageZipTarballを実行して得られた実行ファイルを起動すると、ProdServerStartのmainから実行が始まるという雰囲気。
まとめ
playframeworkのsbt pluginを有効にしたときの、runやcompileの挙動周りを調べた。奥がだいぶ深かった。ちょっと知識が深まった気がする。