1. Qiita
  2. Items
  3. Scala

なぜあなたの sbt はすぐに起動しないのか

  • 73
    Like
  • 0
    Comment
More than 1 year has passed since last update.

特に Scala 初心者だったとき、Scala を始めようとして「なかなか jar ファイルが落ちてこなくてコードが書き始められない」という問題に遭遇したことがある方も多いのではないかと思います。Advent Calendar の穴埋めのネタとして、それについて少し説明してみようと思います。

参考:下り 60Mbps での結果

http://qiita.com/seratch@github/items/0df29e637a9f9b3d7dec

sbt (Scala Build Tool)

まず前提として Scala のビルドツールは GradleMaven も利用可能ですが、Typesafe 社が開発している sbt というビルドツールが主流です。

この記事時点での最新バージョンは 0.13.9 です。 https://github.com/sbt/sbt/releases

このところ 0.13 のシリーズがそれなりに長く続いていましたが、今年の ScalaDays(サンフランシスコ)では、sbt コアチームから 1.0 のリリースに向けたロードマップが示されたという状況にあります。

Play Framework など多くの主要な Scala OSS は sbt の利用を前提としているので、今回はこの sbt を使うことを前提として説明します。

sbt をセットアップする

Scala 2.11 のコードをとにかく何か書き始めようと思ったときに必要なもの、それは

  • java -jar sbt-launch.jar を起動するためのスクリプト
  • 最低限の sbt ビルド設定

です。

前者は Mac OS X であれば Homebrew を使って brew install sbt だけで OK です。Windows や Linux の場合はこの辺のドキュメントを参照してください。 http://www.scala-sbt.org/0.13/tutorial/ja/Setup.html

最低限の sbt ビルド設定

最低限のビルド設定、実はこれだけです。build.sbt というファイル名で保存します。

scalaVersion := "2.11.7"

本当はこれすらなくても sbt 自体は起動するのですが、なぜ Scala のバージョンを指定しているかについて少し説明します。

まず、こちらを見ていただければお分かりいただけるかと思いますが

Screen Shot 0027-12-24 at 16.20.37.png

https://github.com/sbt/sbt

sbt は Scala で書かれたアプリケーションをビルドするツールでありつつ、sbt それ自身も Scala で実装されています。

よって、その動作にあたり、特定の Scala のバージョンに依存しています。0.13.9 時点では、その依存する Scala のバージョンは 2.10 です。そして、scalaVersion を指定しない場合にデフォルトで sbt 0.13.9 がビルドする Scala アプリケーションが依存する Scala のバージョンは 2.10.5 となります。

一方、昨年春にリリースされてから 1 年半以上が経ち Scala 2.11 は十分に普及しており、ほとんどの人は 2.11 を使っている状況ですので、最低限必要なものとして 2.11 の指定をしているというわけです。

・・・ただ、この辺は Scala を始めたばかりの方にとっては非常にわかりにくいと思いますので、少し補足しておきます。

まず、前提として Scala は 2.10 と 2.11 のように 2.x の x のバージョンリリース毎にバイナリ互換性が保証されません。よって、Scala 2.10 で動作するようにビルドされた Scala のプログラムであるところの sbt 0.13.9 は Scala 2.11 で動かすことはできません。そのため

  • sbt 自身の実行は Scala 2.10 に依存する
  • 今回のビルド対象のコードは(コンパイラを含む)Scala 2.11 に依存する

といった状態になるのですが、ご理解いただけたでしょうか? ・・・といっても、これ以上はうまく説明できる自信がないので、ご理解いただけたという前提で進めます。

また、sbt 設定ファイルの記法についても少し補足します。現在 sbt には 3 種類の記述方法が存在していて、上記はそのうち「bare .sbt ビルド定義」と呼ばれているものです。説明上、最もシンプルなのでその記述にしていますが「マルチプロジェクトでの .sbt ビルド定義」という記述が今後は推奨とのことなので、本家のドキュメントも読んでみてください。 http://www.scala-sbt.org/0.13/tutorial/ja/Basic-Def.html

それでは本題に戻ります。

実際のダウンロードの様子

まっさらな状態で sbt を起動するために一体どれくらい jar ファイルが必要なのかデモするために、デフォルトでは $HOME/.ivy2/cache である依存ライブラリのダウンロード先を何もない別のディレクトリに変更してみましょう。

$ export SBT_OPTS="$SBT_OPTS -Dsbt.ivy.home=./ivy2"

この状態で sbt を起動します。すると、以下のような jar ダウンロードを待つことになります。

$ time sbt update
[info] Loading global plugins from /Users/k-sera/.sbt/0.13/plugins
[info] Updating {file:/Users/k-sera/.sbt/0.13/plugins/}global-plugins...
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[info] downloading https://jcenter.bintray.com/org/scala-lang/scala-library/2.10.5/scala-library-2.10.5.jar ...
[info]  [SUCCESSFUL ] org.scala-lang#scala-library;2.10.5!scala-library.jar (113589ms)
[info] downloading https://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/sbt/0.13.9/jars/sbt.jar ...
[info]  [SUCCESSFUL ] org.scala-sbt#sbt;0.13.9!sbt.jar (4454ms)
[info] downloading https://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/main/0.13.9/jars/main.jar ...
[info]  [SUCCESSFUL ] org.scala-sbt#main;0.13.9!main.jar (17396ms)
[info] downloading https://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/compiler-interface/0.13.9/jars/compiler-interface-bin.jar ...
[info]  [SUCCESSFUL ] org.scala-sbt#compiler-interface;0.13.9!compiler-interface-bin.jar (7994ms)
[info] downloading https://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/compiler-interface/0.13.9/jars/compiler-interface-src.jar ...
[info]  [SUCCESSFUL ] org.scala-sbt#compiler-interface;0.13.9!compiler-interface-src.jar (3777ms)
[info] downloading https://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/precompiled-2_8_2/0.13.9/jars/compiler-interface-bin.jar ...
[info]  [SUCCESSFUL ] org.scala-sbt#precompiled-2_8_2;0.13.9!compiler-interface-bin.jar (6356ms)
[info] downloading https://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/precompiled-2_9_2/0.13.9/jars/compiler-interface-bin.jar ...
[info]  [SUCCESSFUL ] org.scala-sbt#precompiled-2_9_2;0.13.9!compiler-interface-bin.jar (5063ms)
[info] downloading https://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/precompiled-2_9_3/0.13.9/jars/compiler-interface-bin.jar ...
[info]  [SUCCESSFUL ] org.scala-sbt#precompiled-2_9_3;0.13.9!compiler-interface-bin.jar (4954ms)
[info] downloading https://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/actions/0.13.9/jars/actions.jar ...
[info]  [SUCCESSFUL ] org.scala-sbt#actions;0.13.9!actions.jar (6533ms)
[info] downloading https://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/main-settings/0.13.9/jars/main-settings.jar ...
[info]  [SUCCESSFUL ] org.scala-sbt#main-settings;0.13.9!main-settings.jar (5790ms)
[info] downloading https://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/interface/0.13.9/jars/interface.jar ...
[info]  [SUCCESSFUL ] org.scala-sbt#interface;0.13.9!interface.jar (4196ms)
[info] downloading https://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/io/0.13.9/jars/io.jar ...
[info]  [SUCCESSFUL ] org.scala-sbt#io;0.13.9!io.jar (6969ms)
[info] downloading https://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/ivy/0.13.9/jars/ivy.jar ...
[info]  [SUCCESSFUL ] org.scala-sbt#ivy;0.13.9!ivy.jar (17536ms)
[info] downloading https://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/logging/0.13.9/jars/logging.jar ...
[info]  [SUCCESSFUL ] org.scala-sbt#logging;0.13.9!logging.jar (6343ms)
[info] downloading https://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/logic/0.13.9/jars/logic.jar ...
[info]  [SUCCESSFUL ] org.scala-sbt#logic;0.13.9!logic.jar (4210ms)
[info] downloading https://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/process/0.13.9/jars/process.jar ...
[info]  [SUCCESSFUL ] org.scala-sbt#process;0.13.9!process.jar (4225ms)
[info] downloading https://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/run/0.13.9/jars/run.jar ...
[info]  [SUCCESSFUL ] org.scala-sbt#run;0.13.9!run.jar (4955ms)
[info] downloading https://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/command/0.13.9/jars/command.jar ...
[info]  [SUCCESSFUL ] org.scala-sbt#command;0.13.9!command.jar (8676ms)
[info] downloading https://jcenter.bintray.com/org/scala-sbt/launcher-interface/1.0.0-M1/launcher-interface-1.0.0-M1.jar ...
[info]  [SUCCESSFUL ] org.scala-sbt#launcher-interface;1.0.0-M1!launcher-interface.jar (936ms)
[info] downloading https://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/classpath/0.13.9/jars/classpath.jar ...
[info]  [SUCCESSFUL ] org.scala-sbt#classpath;0.13.9!classpath.jar (4759ms)
[info] downloading https://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/completion/0.13.9/jars/completion.jar ...
[info]  [SUCCESSFUL ] org.scala-sbt#completion;0.13.9!completion.jar (8712ms)
[info] downloading https://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/api/0.13.9/jars/api.jar ...
[info]  [SUCCESSFUL ] org.scala-sbt#api;0.13.9!api.jar (5876ms)
[info] downloading https://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/compiler-integration/0.13.9/jars/compiler-integration.jar ...
[info]  [SUCCESSFUL ] org.scala-sbt#compiler-integration;0.13.9!compiler-integration.jar (5074ms)
[info] downloading https://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/compiler-ivy-integration/0.13.9/jars/compiler-ivy-integration.jar ...
[info]  [SUCCESSFUL ] org.scala-sbt#compiler-ivy-integration;0.13.9!compiler-ivy-integration.jar (4281ms)
[info] downloading https://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/relation/0.13.9/jars/relation.jar ...
[info]  [SUCCESSFUL ] org.scala-sbt#relation;0.13.9!relation.jar (3837ms)
[info] downloading https://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/task-system/0.13.9/jars/task-system.jar ...
[info]  [SUCCESSFUL ] org.scala-sbt#task-system;0.13.9!task-system.jar (4249ms)
[info] downloading https://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/tasks/0.13.9/jars/tasks.jar ...
[info]  [SUCCESSFUL ] org.scala-sbt#tasks;0.13.9!tasks.jar (4151ms)
[info] downloading https://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/tracking/0.13.9/jars/tracking.jar ...
[info]  [SUCCESSFUL ] org.scala-sbt#tracking;0.13.9!tracking.jar (3854ms)
[info] downloading https://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/testing/0.13.9/jars/testing.jar ...
[info]  [SUCCESSFUL ] org.scala-sbt#testing;0.13.9!testing.jar (4265ms)
[info] downloading https://jcenter.bintray.com/org/scala-lang/scala-compiler/2.10.5/scala-compiler-2.10.5.jar ...
[info]  [SUCCESSFUL ] org.scala-lang#scala-compiler;2.10.5!scala-compiler.jar (105375ms)
[info] downloading https://jcenter.bintray.com/org/scala-lang/scala-reflect/2.10.5/scala-reflect-2.10.5.jar ...
[info]  [SUCCESSFUL ] org.scala-lang#scala-reflect;2.10.5!scala-reflect.jar (22318ms)
[info] downloading https://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/control/0.13.9/jars/control.jar ...
[info]  [SUCCESSFUL ] org.scala-sbt#control;0.13.9!control.jar (5574ms)
[info] downloading https://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/collections/0.13.9/jars/collections.jar ...
[info]  [SUCCESSFUL ] org.scala-sbt#collections;0.13.9!collections.jar (5608ms)
[info] downloading https://jcenter.bintray.com/jline/jline/2.11/jline-2.11.jar ...
[info]  [SUCCESSFUL ] jline#jline;2.11!jline.jar (1669ms)
[info] downloading https://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/incremental-compiler/0.13.9/jars/incremental-compiler.jar ...
[info]  [SUCCESSFUL ] org.scala-sbt#incremental-compiler;0.13.9!incremental-compiler.jar (5009ms)
[info] downloading https://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/compile/0.13.9/jars/compile.jar ...
[info]  [SUCCESSFUL ] org.scala-sbt#compile;0.13.9!compile.jar (4635ms)
[info] downloading https://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/persist/0.13.9/jars/persist.jar ...
[info]  [SUCCESSFUL ] org.scala-sbt#persist;0.13.9!persist.jar (6312ms)
[info] downloading https://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/classfile/0.13.9/jars/classfile.jar ...
[info]  [SUCCESSFUL ] org.scala-sbt#classfile;0.13.9!classfile.jar (4624ms)
[info] downloading https://repo.typesafe.com/typesafe/ivy-releases/org.scala-tools.sbinary/sbinary_2.10/0.4.2/jars/sbinary_2.10.jar ...
[info]  [SUCCESSFUL ] org.scala-tools.sbinary#sbinary_2.10;0.4.2!sbinary_2.10.jar (6300ms)
[info] downloading https://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/cross/0.13.9/jars/cross.jar ...
[info]  [SUCCESSFUL ] org.scala-sbt#cross;0.13.9!cross.jar (4860ms)
[info] downloading https://jcenter.bintray.com/org/scala-sbt/ivy/ivy/2.3.0-sbt-c5d1b95fdcc1e1007740ffbecf4eb07abc51ec93/ivy-2.3.0-sbt-c5d1b95fdcc1e1007740ffbecf4eb07abc51ec93.jar ...
[info]  [SUCCESSFUL ] org.scala-sbt.ivy#ivy;2.3.0-sbt-c5d1b95fdcc1e1007740ffbecf4eb07abc51ec93!ivy.jar (4797ms)
[info] downloading https://jcenter.bintray.com/com/jcraft/jsch/0.1.46/jsch-0.1.46.jar ...
[info]  [SUCCESSFUL ] com.jcraft#jsch;0.1.46!jsch.jar (2392ms)
[info] downloading https://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/serialization_2.10/0.1.1/jars/serialization_2.10.jar ...
[info]  [SUCCESSFUL ] org.scala-sbt#serialization_2.10;0.1.1!serialization_2.10.jar (7828ms)
[info] downloading https://jcenter.bintray.com/org/scala-lang/modules/scala-pickling_2.10/0.10.0/scala-pickling_2.10-0.10.0.jar ...
[info]  [SUCCESSFUL ] org.scala-lang.modules#scala-pickling_2.10;0.10.0!scala-pickling_2.10.jar (5673ms)
[info] downloading https://jcenter.bintray.com/org/json4s/json4s-core_2.10/3.2.10/json4s-core_2.10-3.2.10.jar ...
[info]  [SUCCESSFUL ] org.json4s#json4s-core_2.10;3.2.10!json4s-core_2.10.jar (3021ms)
[info] downloading https://jcenter.bintray.com/org/spire-math/jawn-parser_2.10/0.6.0/jawn-parser_2.10-0.6.0.jar ...
[info]  [SUCCESSFUL ] org.spire-math#jawn-parser_2.10;0.6.0!jawn-parser_2.10.jar (1112ms)
[info] downloading https://jcenter.bintray.com/org/spire-math/json4s-support_2.10/0.6.0/json4s-support_2.10-0.6.0.jar ...
[info]  [SUCCESSFUL ] org.spire-math#json4s-support_2.10;0.6.0!json4s-support_2.10.jar (652ms)
[info] downloading https://jcenter.bintray.com/org/scalamacros/quasiquotes_2.10/2.0.1/quasiquotes_2.10-2.0.1.jar ...
[info]  [SUCCESSFUL ] org.scalamacros#quasiquotes_2.10;2.0.1!quasiquotes_2.10.jar (3766ms)
[info] downloading https://jcenter.bintray.com/org/json4s/json4s-ast_2.10/3.2.10/json4s-ast_2.10-3.2.10.jar ...
[info]  [SUCCESSFUL ] org.json4s#json4s-ast_2.10;3.2.10!json4s-ast_2.10.jar (1125ms)
[info] downloading https://jcenter.bintray.com/com/thoughtworks/paranamer/paranamer/2.6/paranamer-2.6.jar ...
[info]  [SUCCESSFUL ] com.thoughtworks.paranamer#paranamer;2.6!paranamer.jar (828ms)
[info] downloading https://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/cache/0.13.9/jars/cache.jar ...
[info]  [SUCCESSFUL ] org.scala-sbt#cache;0.13.9!cache.jar (4541ms)
[info] downloading https://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/test-agent/0.13.9/jars/test-agent.jar ...
[info]  [SUCCESSFUL ] org.scala-sbt#test-agent;0.13.9!test-agent.jar (3815ms)
[info] downloading https://jcenter.bintray.com/org/scala-sbt/test-interface/1.0/test-interface-1.0.jar ...
[info]  [SUCCESSFUL ] org.scala-sbt#test-interface;1.0!test-interface.jar (1438ms)
[info] downloading https://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/apply-macro/0.13.9/jars/apply-macro.jar ...
[info]  [SUCCESSFUL ] org.scala-sbt#apply-macro;0.13.9!apply-macro.jar (4169ms)
[info] downloading https://jcenter.bintray.com/org/scala-lang/jline/2.10.5/jline-2.10.5.jar ...
[info]  [SUCCESSFUL ] org.scala-lang#jline;2.10.5!jline.jar (3439ms)
[info] downloading https://jcenter.bintray.com/org/fusesource/jansi/jansi/1.4/jansi-1.4.jar ...
[info]  [SUCCESSFUL ] org.fusesource.jansi#jansi;1.4!jansi.jar (2247ms)
[info] Done updating.
[info] Set current project to sbt-deps (in build file:/Users/k-sera/tmp/sbt-deps/)
[info] Updating {file:/Users/k-sera/tmp/sbt-deps/}sbt-deps...
[info] Resolving org.sonatype.oss#oss-parent;7 ...
[info] downloading https://jcenter.bintray.com/org/scala-lang/scala-library/2.11.7/scala-library-2.11.7.jar ...
[info]  [SUCCESSFUL ] org.scala-lang#scala-library;2.11.7!scala-library.jar (28318ms)
[info] downloading https://jcenter.bintray.com/org/scala-lang/scala-compiler/2.11.7/scala-compiler-2.11.7.jar ...
[info]  [SUCCESSFUL ] org.scala-lang#scala-compiler;2.11.7!scala-compiler.jar (143161ms)
[info] downloading https://jcenter.bintray.com/org/scala-lang/scala-reflect/2.11.7/scala-reflect-2.11.7.jar ...
[info]  [SUCCESSFUL ] org.scala-lang#scala-reflect;2.11.7!scala-reflect.jar (18146ms)
[info] downloading https://jcenter.bintray.com/org/scala-lang/modules/scala-xml_2.11/1.0.4/scala-xml_2.11-1.0.4.jar ...
[info]  [SUCCESSFUL ] org.scala-lang.modules#scala-xml_2.11;1.0.4!scala-xml_2.11.jar(bundle) (4835ms)
[info] downloading https://jcenter.bintray.com/org/scala-lang/modules/scala-parser-combinators_2.11/1.0.4/scala-parser-combinators_2.11-1.0.4.jar ...
[info]  [SUCCESSFUL ] org.scala-lang.modules#scala-parser-combinators_2.11;1.0.4!scala-parser-combinators_2.11.jar(bundle) (3321ms)
[info] downloading https://jcenter.bintray.com/jline/jline/2.12.1/jline-2.12.1.jar ...
[info]  [SUCCESSFUL ] jline#jline;2.12.1!jline.jar (2507ms)
[info] Done updating.
[success] Total time: 207 s, completed 2015/12/24 16:01:50

real    16m56.993s
user    0m33.941s
sys 0m4.600s

約 17 分かかったようです...。ただし、これは比較的ワーストケースであることは言及しておくべきで、ネットワーク環境の状況や jcenter.bintray.com の調子(?)によってかなり変動します。とはいえ、かなりスムーズなときでも 10 分程度はかかるのが実際のところといってよいでしょう。

注目すべき点は org.scala-lang の依存ライブラリダウンロードです。後述しますが、これがかなり多くの時間を消費しています。上記の出力で「Total time: 207 s」と表示されているこの「207 秒」というのは sbt 自身の準備が完了してから、いよいよ Scala 2.11.7 をダウンロードと Scala コンパイルが可能な状態にするためだけに必要とした時間です。

jar ファイルのサイズを見る

個別に細かく見る前にダウンロードされたファイルのサイズをざっと見てみます。実際には jar ファイル以外もダウンロードされているのですが、最も大きいのは jar ファイルですので、そのサイズを見てみましょう。

$ tree -h | grep jar$
│       │           └── [220K]  jsch-0.1.46.jar
│       │   │       └── [ 32K]  paranamer-2.6.jar
│       │           ├── [204K]  jline-2.11.jar
│       │           └── [209K]  jline-2.12.1.jar
│       │           └── [104K]  jansi-1.4.jar
│       │   │       └── [ 82K]  json4s-ast_2.10-3.2.10.jar
│       │           └── [571K]  json4s-core_2.10-3.2.10.jar
│       │   │       └── [161K]  jline-2.10.5.jar
│       │   │       ├── [ 14M]  scala-compiler-2.10.5.jar
│       │   │       └── [ 15M]  scala-compiler-2.11.7.jar
│       │   │       ├── [6.8M]  scala-library-2.10.5.jar
│       │   │       └── [5.5M]  scala-library-2.11.7.jar
│       │           ├── [3.1M]  scala-reflect-2.10.5.jar
│       │           └── [4.4M]  scala-reflect-2.11.7.jar
│       │   │   │   └── [414K]  scala-parser-combinators_2.11-1.0.4.jar
│       │   │       └── [805K]  scala-pickling_2.10-0.10.0.jar
│       │       │   └── [633K]  scala-xml_2.11-1.0.4.jar
│       │   │       └── [473K]  actions-0.13.9.jar
│       │   │       └── [319K]  api-0.13.9.jar
│       │   │       └── [ 85K]  apply-macro-0.13.9.jar
│       │   │       └── [113K]  cache-0.13.9.jar
│       │   │       └── [ 81K]  classfile-0.13.9.jar
│       │   │       └── [ 86K]  classpath-0.13.9.jar
│       │   │       └── [415K]  collections-0.13.9.jar
│       │   │       └── [236K]  command-0.13.9.jar
│       │   │       └── [234K]  compile-0.13.9.jar
│       │   │       └── [125K]  compiler-integration-0.13.9.jar
│       │   │       ├── [236K]  compiler-interface-bin-0.13.9.jar
│       │   │       └── [ 30K]  compiler-interface-src-0.13.9.jar
│       │   │       └── [8.5K]  compiler-ivy-integration-0.13.9.jar
│       │   │       └── [378K]  completion-0.13.9.jar
│       │   │       └── [ 13K]  control-0.13.9.jar
│       │   │       └── [8.0K]  cross-0.13.9.jar
│       │   │       └── [478K]  incremental-compiler-0.13.9.jar
│       │   │       └── [ 52K]  interface-0.13.9.jar
│       │   │       └── [269K]  io-0.13.9.jar
│       │   │       └── [1.8M]  ivy-0.13.9.jar
│       │   │       └── [9.8K]  launcher-interface-1.0.0-M1.jar
│       │   │       └── [106K]  logging-0.13.9.jar
│       │   │       └── [ 63K]  logic-0.13.9.jar
│       │   │       └── [2.4M]  main-0.13.9.jar
│       │   │       └── [641K]  main-settings-0.13.9.jar
│       │   │       └── [160K]  persist-0.13.9.jar
│       │   │       └── [223K]  compiler-interface-bin-0.13.9.jar
│       │   │       └── [233K]  compiler-interface-bin-0.13.9.jar
│       │   │       └── [233K]  compiler-interface-bin-0.13.9.jar
│       │   │       └── [121K]  process-0.13.9.jar
│       │   │       └── [ 29K]  relation-0.13.9.jar
│       │   │       └── [129K]  run-0.13.9.jar
│       │   │       └── [ 21K]  sbt-0.13.9.jar
│       │   │       └── [325K]  serialization_2.10-0.1.1.jar
│       │   │       └── [128K]  task-system-0.13.9.jar
│       │   │       └── [127K]  tasks-0.13.9.jar
│       │   │       └── [ 23K]  test-agent-0.13.9.jar
│       │   │       └── [ 14K]  test-interface-1.0.jar
│       │   │       └── [100K]  testing-0.13.9.jar
│       │           └── [ 49K]  tracking-0.13.9.jar
│       │           └── [1.1M]  ivy-2.3.0-sbt-c5d1b95fdcc1e1007740ffbecf4eb07abc51ec93.jar
│       │           └── [148K]  sbinary_2.10-0.4.2.jar
│       │           └── [704K]  quasiquotes_2.10-2.0.1.jar
│           │       └── [ 76K]  jawn-parser_2.10-0.6.0.jar
│                   └── [7.4K]  json4s-support_2.10-0.6.0.jar
│       │           └── [220K]  jsch-0.1.46.jar
│       │   │       └── [ 32K]  paranamer-2.6.jar
│       │           ├── [204K]  jline-2.11.jar
│       │           └── [209K]  jline-2.12.1.jar
│       │           └── [104K]  jansi-1.4.jar
│       │   │       └── [ 82K]  json4s-ast_2.10-3.2.10.jar
│       │           └── [571K]  json4s-core_2.10-3.2.10.jar
│       │   │       └── [161K]  jline-2.10.5.jar
│       │   │       ├── [ 14M]  scala-compiler-2.10.5.jar
│       │   │       └── [ 15M]  scala-compiler-2.11.7.jar
│       │   │       ├── [6.8M]  scala-library-2.10.5.jar
│       │   │       └── [5.5M]  scala-library-2.11.7.jar
│       │           ├── [3.1M]  scala-reflect-2.10.5.jar
│       │           └── [4.4M]  scala-reflect-2.11.7.jar
│       │   │   │   └── [414K]  scala-parser-combinators_2.11-1.0.4.jar
│       │   │       └── [805K]  scala-pickling_2.10-0.10.0.jar
│       │       │   └── [633K]  scala-xml_2.11-1.0.4.jar
│       │   │       └── [473K]  actions-0.13.9.jar
│       │   │       └── [319K]  api-0.13.9.jar
│       │   │       └── [ 85K]  apply-macro-0.13.9.jar
│       │   │       └── [113K]  cache-0.13.9.jar
│       │   │       └── [ 81K]  classfile-0.13.9.jar
│       │   │       └── [ 86K]  classpath-0.13.9.jar
│       │   │       └── [415K]  collections-0.13.9.jar
│       │   │       └── [236K]  command-0.13.9.jar
│       │   │       └── [234K]  compile-0.13.9.jar
│       │   │       └── [125K]  compiler-integration-0.13.9.jar
│       │   │       ├── [236K]  compiler-interface-bin-0.13.9.jar
│       │   │       └── [ 30K]  compiler-interface-src-0.13.9.jar
│       │   │       └── [8.5K]  compiler-ivy-integration-0.13.9.jar
│       │   │       └── [378K]  completion-0.13.9.jar
│       │   │       └── [ 13K]  control-0.13.9.jar
│       │   │       └── [8.0K]  cross-0.13.9.jar
│       │   │       └── [478K]  incremental-compiler-0.13.9.jar
│       │   │       └── [ 52K]  interface-0.13.9.jar
│       │   │       └── [269K]  io-0.13.9.jar
│       │   │       └── [1.8M]  ivy-0.13.9.jar
│       │   │       └── [9.8K]  launcher-interface-1.0.0-M1.jar
│       │   │       └── [106K]  logging-0.13.9.jar
│       │   │       └── [ 63K]  logic-0.13.9.jar
│       │   │       └── [2.4M]  main-0.13.9.jar
│       │   │       └── [641K]  main-settings-0.13.9.jar
│       │   │       └── [160K]  persist-0.13.9.jar
│       │   │       └── [223K]  compiler-interface-bin-0.13.9.jar
│       │   │       └── [233K]  compiler-interface-bin-0.13.9.jar
│       │   │       └── [233K]  compiler-interface-bin-0.13.9.jar
│       │   │       └── [121K]  process-0.13.9.jar
│       │   │       └── [ 29K]  relation-0.13.9.jar
│       │   │       └── [129K]  run-0.13.9.jar
│       │   │       └── [ 21K]  sbt-0.13.9.jar
│       │   │       └── [325K]  serialization_2.10-0.1.1.jar
│       │   │       └── [128K]  task-system-0.13.9.jar
│       │   │       └── [127K]  tasks-0.13.9.jar
│       │   │       └── [ 23K]  test-agent-0.13.9.jar
│       │   │       └── [ 14K]  test-interface-1.0.jar
│       │   │       └── [100K]  testing-0.13.9.jar
│       │           └── [ 49K]  tracking-0.13.9.jar
│       │           └── [1.1M]  ivy-2.3.0-sbt-c5d1b95fdcc1e1007740ffbecf4eb07abc51ec93.jar
│       │           └── [148K]  sbinary_2.10-0.4.2.jar
│       │           └── [704K]  quasiquotes_2.10-2.0.1.jar
│           │       └── [ 76K]  jawn-parser_2.10-0.6.0.jar
│                   └── [7.4K]  json4s-support_2.10-0.6.0.jar

scala-compiler-x.y.z の巨大さが際立ちます。

│       │   │       ├── [ 14M]  scala-compiler-2.10.5.jar
│       │   │       └── [ 15M]  scala-compiler-2.11.7.jar

その分、この二つの jar のダウンロード時間は相当に長いです。今回試した環境だと 100 秒を超えてくる感じです。

[info] downloading https://jcenter.bintray.com/org/scala-lang/scala-compiler/2.11.7/scala-compiler-2.11.7.jar ...
[info]  [SUCCESSFUL ] org.scala-lang#scala-compiler;2.11.7!scala-compiler.jar (143161ms)
[info] downloading https://jcenter.bintray.com/org/scala-lang/scala-compiler/2.10.5/scala-compiler-2.10.5.jar ...
[info]  [SUCCESSFUL ] org.scala-lang#scala-compiler;2.10.5!scala-compiler.jar (105375ms)

主要なダウンロード内容

上記に貼り付けた多数の jar ファイルダウンロードのうち主要なものについて、先ほどの説明と一部重複しますが、改めて説明します。

Scala 2.11.7

Scala 2.11 で書かれたアプリケーションをコンパイルするためには scala-compiler-2.11.x が必要です。また、標準 API の集合である scala-library-2.11.x とその他のモジュールも必要です。compiler 以外は実行時にも依存するので classpath に追加する必要があります(余談ですが compiler にも依存しているライブラリも存在します)。

[info] downloading https://jcenter.bintray.com/org/scala-lang/scala-library/2.11.7/scala-library-2.11.7.jar ...
[info]  [SUCCESSFUL ] org.scala-lang#scala-library;2.11.7!scala-library.jar (28318ms)
[info] downloading https://jcenter.bintray.com/org/scala-lang/scala-compiler/2.11.7/scala-compiler-2.11.7.jar ...
[info]  [SUCCESSFUL ] org.scala-lang#scala-compiler;2.11.7!scala-compiler.jar (143161ms)
[info] downloading https://jcenter.bintray.com/org/scala-lang/scala-reflect/2.11.7/scala-reflect-2.11.7.jar ...
[info]  [SUCCESSFUL ] org.scala-lang#scala-reflect;2.11.7!scala-reflect.jar (18146ms)
[info] downloading https://jcenter.bintray.com/org/scala-lang/modules/scala-xml_2.11/1.0.4/scala-xml_2.11-1.0.4.jar ...
[info]  [SUCCESSFUL ] org.scala-lang.modules#scala-xml_2.11;1.0.4!scala-xml_2.11.jar(bundle) (4835ms)
[info] downloading https://jcenter.bintray.com/org/scala-lang/modules/scala-parser-combinators_2.11/1.0.4/scala-parser-combinators_2.11-1.0.4.jar ...
[info]  [SUCCESSFUL ] org.scala-lang.modules#scala-parser-combinators_2.11;1.0.4!scala-parser-combinators_2.11.jar(bundle) (3321ms)

Scala 2.10.5

Scala 2.10 を使っていない場合でも sbt 0.13.9 を使うためには Scala 2.11 のアプリをコンパイルする場合であっても Scala 2.10 が必要なのでダウンロードしています。詳細は次の sbt 0.13.9 のセクションで説明します。

[info] downloading https://jcenter.bintray.com/org/scala-lang/scala-library/2.10.5/scala-library-2.10.5.jar ...
[info]  [SUCCESSFUL ] org.scala-lang#scala-library;2.10.5!scala-library.jar (113589ms)
[info] downloading https://jcenter.bintray.com/org/scala-lang/scala-compiler/2.10.5/scala-compiler-2.10.5.jar ...
[info]  [SUCCESSFUL ] org.scala-lang#scala-compiler;2.10.5!scala-compiler.jar (105375ms)
[info] downloading https://jcenter.bintray.com/org/scala-lang/scala-reflect/2.10.5/scala-reflect-2.10.5.jar ...
[info]  [SUCCESSFUL ] org.scala-lang#scala-reflect;2.10.5!scala-reflect.jar (22318ms)
[info] downloading https://jcenter.bintray.com/org/scala-lang/modules/scala-pickling_2.10/0.10.0/scala-pickling_2.10-0.10.0.jar ...
[info]  [SUCCESSFUL ] org.scala-lang.modules#scala-pickling_2.10;0.10.0!scala-pickling_2.10.jar (5673ms)
[info] downloading https://jcenter.bintray.com/org/scala-lang/jline/2.10.5/jline-2.10.5.jar ...
[info]  [SUCCESSFUL ] org.scala-lang#jline;2.10.5!jline.jar (3439ms)

sbt 0.13.9

sbt はそのリリース毎に本体のライブラリ群とは独立した sbt-launch.jar(公式の表現ではないですが、ここでは sbt ランチャーと呼びます)というスタンドアローンで起動できる jar ファイルを提供していています。

工夫されている点として、もし使っている sbt ランチャーがちょっと古くて 0.13.8 だった場合でも project/build.propertiessbt.version=0.13.9 と記述しておくと、sbt ランチャーのビルドバージョンである 0.13.8 ではなく、指定された 0.13.9 の sbt をダウンロードしてきて sbt 0.13.9 として起動することができるようになっています。逆に、もし sbt ランチャーが 0.13.8 のもので project/build.properties で指定がされていない状態だと 0.13.9 が最新であってもデフォルトで sbt 0.13.8 のライブラリ群をダウンロードして sbt 0.13.8 として起動します。このように一つのランチャーで複数の 0.13.x マイナーバージョンを使うことができるようになっているわけです。

・・・と、ここも Scala 初心者の方にも伝わるように説明できたか少し不安ですが、これもご理解いただけたという前提で進めます。

もし $HOME/.ivy2/cache に sbt 0.13.9 の依存ライブラリが存在しなかった場合、この sbt 0.13.9 自体のダウンロードが java -jar sbt-launcher.jar で起動した Java プロセスによって行われます。そのログが上記に貼り付けたダウンロード時の標準出力における [info] Done updating. までの全てのダウンロードとなります。

sbt 0.13.9 が起動するために必要とするものをざっくりまとめると

  • org.scala-sbt のライブラリ群
  • org.scala-sbt のライブラリ群が依存するいくつかの 3rd party ライブラリ群
  • sbt が依存するコンパイラも含む Scala のフルダウンロード(0.13.9 の場合は 2.10.5)

ということになります。

まっさらな環境の話

ここまでで、なぜ sbt の初期起動時にあれほど多くの jar ダウンロードが必要となっているか、その背景がおわかりいただけたのではないかと思います。二つの Scala バージョンのコンパイラを含むフルダウンロードと sbt 自身のダウンロードが必要ということですね。

これはあくまでまっさらな環境で初めて sbt を起動したときに限った話ではあり、一度ダウンロードしてしまえばそれ以降はこのような問題はありません。しかし、まっさらな環境ですぐに sbt を使って Scala コンパイルをしようとしても、上記で見たようなダウンロードが終わるまでは何もできないということもまた無視できない問題ではあります。

Scala コミュニティがとった対応策

このような状況に Typesafe 社をはじめとする Scala コミュニティは何もアクションをとっていないかというと、そんなことはありません。具体的には jar ファイルのサイズの削減は今すぐにどうにかなる問題ではないので、ダウンロード自体をショートカットできるものを提供するという対応策をとっています。

Typesafe Activator

Typesafe 社が提供する sbt にブラウザでアクセスできる GUI やプロジェクトテンプレートのダウンロード機能を追加した Activator というツールがあります。これのダウンロードページを見るとファイルサイズが 477M と書かれています。

https://www.typesafe.com/activator/download

Screen Shot 0027-12-24 at 17.13.23.png

なぜそれほど巨大なものをダウンロードするのでしょう?そう、上記の jar ダウンロードをショートカットするために予め必須の jar ファイルが含まれているのです。一方、

Or download the mini-package with no bundled dependencies (1M)

という表記の方は、このようにランチャーだけが存在するバージョンです。

Homebrew で提供されている activator の Formula(typesafe-activator)はかつては 477MB のフルバージョンでしたが、最近はこのランチャーだけの方になったようです。Scala 初心者の方が brew install typesafe-activator してから activator を立ち上げようとするとやたらとダウンロードが始まるのはこのためです。

$ cd activator-1.3.7-minimal/
$ tree
.
├── activator
├── activator-launch-1.3.7.jar
└── activator.bat

0 directories, 3 files

skinny-blank-app-with-deps.zip

手前味噌ながら、私は Skinny Framework という "Scala on Rails" をキャッチコピーとする Web フレームワークの開発をしているのですが、この Skinny プロジェクトでも同じように(やり方は少し違うのですが) jar ファイルを含むサイズの大きめな zip ファイルを配布しています。こちらは 90MB 程度のファイルです。

http://skinny-framework.org/

Screen Shot 0027-12-24 at 17.36.28.png

これの skinny-blank-app-with-deps.zip をダウンロードして解凍するとまっさらな環境でも jar のダウンロードを一切しなくても済むようになっています。ちなみに Skinny も Homebrew の Formula(skinny)を提供していますが、こちらは jar を含むサイズの大きい方を配布していますので Homebrew から入れたときでも jar ダウンロードをショートカットできます。

Play は本当に巨大なフレームワークか?

さて、Scala の最もメジャーな Web フレームワークである Play Framework は一般的に何となく「機能が多くて、依存ライブラリも多い重厚なフレームワーク」というイメージが持たれているように思いますが、果たして本当にそうでしょうか?

今回のテーマである jar ファイルのダウンロードという側面でそれについて少し書いてみたいと思います。

まず Play アプリケーションの最低限の sbt ビルド設定は以下の通りです。

build.sbt

lazy val root = (project in file(".")).enablePlugins(PlayScala)
scalaVersion := "2.11.7"
libraryDependencies ++= Seq(
  jdbc,
  cache,
  ws,
  specs2 % Test
)
resolvers += "scalaz-bintray" at "http://dl.bintray.com/scalaz/releases"
routesGenerator := InjectedRoutesGenerator

project/plugins.sbt

addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.4.6")

ダウンロードしてみる

この状態で依存ライブラリをダウンロードしてみました。すると、実は Play プロジェクト以外の依存関係もなく、ダウンロードする jar ファイルの数も少ないことがわかります。

$ time sbt update
[info] Loading global plugins from /Users/k-sera/.sbt/0.13/plugins
[info] Updating {file:/Users/k-sera/.sbt/0.13/plugins/}global-plugins...
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[info] Done updating.
[info] Loading project definition from /Users/k-sera/tmp/sbt-deps/project
[info] Updating {file:/Users/k-sera/tmp/sbt-deps/project/}sbt-deps-build...
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[info] downloading https://repo1.maven.org/maven2/org/sonatype/sisu/sisu-guice/3.1.0/sisu-guice-3.1.0.jar ...
[info]  [SUCCESSFUL ] org.sonatype.sisu#sisu-guice;3.1.0!sisu-guice.jar (3484ms)
[info] Done updating.
[info] Set current project to root (in build file:/Users/k-sera/tmp/sbt-deps/)
[info] Updating {file:/Users/k-sera/tmp/sbt-deps/}root...
[info] Resolving jline#jline;2.12.1 ...
[info] downloading https://repo1.maven.org/maven2/com/typesafe/play/play-server_2.11/2.4.6/play-server_2.11-2.4.6.jar ...
[info]  [SUCCESSFUL ] com.typesafe.play#play-server_2.11;2.4.6!play-server_2.11.jar (2833ms)
[info] downloading https://repo1.maven.org/maven2/com/typesafe/play/play-netty-server_2.11/2.4.6/play-netty-server_2.11-2.4.6.jar ...
[info]  [SUCCESSFUL ] com.typesafe.play#play-netty-server_2.11;2.4.6!play-netty-server_2.11.jar (4474ms)
[info] downloading https://repo1.maven.org/maven2/com/typesafe/play/play-jdbc_2.11/2.4.6/play-jdbc_2.11-2.4.6.jar ...
[info]  [SUCCESSFUL ] com.typesafe.play#play-jdbc_2.11;2.4.6!play-jdbc_2.11.jar (2716ms)
[info] downloading https://repo1.maven.org/maven2/com/typesafe/play/play-cache_2.11/2.4.6/play-cache_2.11-2.4.6.jar ...
[info]  [SUCCESSFUL ] com.typesafe.play#play-cache_2.11;2.4.6!play-cache_2.11.jar (1440ms)
[info] downloading https://repo1.maven.org/maven2/com/typesafe/play/play-ws_2.11/2.4.6/play-ws_2.11-2.4.6.jar ...
[info]  [SUCCESSFUL ] com.typesafe.play#play-ws_2.11;2.4.6!play-ws_2.11.jar (5794ms)
[info] downloading https://repo1.maven.org/maven2/com/typesafe/play/play_2.11/2.4.6/play_2.11-2.4.6.jar ...
[info]  [SUCCESSFUL ] com.typesafe.play#play_2.11;2.4.6!play_2.11.jar (30525ms)
[info] downloading https://repo1.maven.org/maven2/com/typesafe/play/play-iteratees_2.11/2.4.6/play-iteratees_2.11-2.4.6.jar ...
[info]  [SUCCESSFUL ] com.typesafe.play#play-iteratees_2.11;2.4.6!play-iteratees_2.11.jar (4814ms)
[info] downloading https://repo1.maven.org/maven2/com/typesafe/play/play-json_2.11/2.4.6/play-json_2.11-2.4.6.jar ...
[info]  [SUCCESSFUL ] com.typesafe.play#play-json_2.11;2.4.6!play-json_2.11.jar (6006ms)
[info] downloading https://repo1.maven.org/maven2/com/typesafe/play/play-netty-utils/2.4.6/play-netty-utils-2.4.6.jar ...
[info]  [SUCCESSFUL ] com.typesafe.play#play-netty-utils;2.4.6!play-netty-utils.jar (615ms)
[info] downloading https://repo1.maven.org/maven2/com/typesafe/play/play-functional_2.11/2.4.6/play-functional_2.11-2.4.6.jar ...
[info]  [SUCCESSFUL ] com.typesafe.play#play-functional_2.11;2.4.6!play-functional_2.11.jar (3071ms)
[info] downloading https://repo1.maven.org/maven2/com/typesafe/play/play-datacommons_2.11/2.4.6/play-datacommons_2.11-2.4.6.jar ...
[info]  [SUCCESSFUL ] com.typesafe.play#play-datacommons_2.11;2.4.6!play-datacommons_2.11.jar (471ms)
[info] downloading https://repo1.maven.org/maven2/com/typesafe/play/play-jdbc-api_2.11/2.4.6/play-jdbc-api_2.11-2.4.6.jar ...
[info]  [SUCCESSFUL ] com.typesafe.play#play-jdbc-api_2.11;2.4.6!play-jdbc-api_2.11.jar (503ms)
[info] downloading https://repo1.maven.org/maven2/com/typesafe/play/play-test_2.11/2.4.6/play-test_2.11-2.4.6.jar ...
[info]  [SUCCESSFUL ] com.typesafe.play#play-test_2.11;2.4.6!play-test_2.11.jar (1900ms)
[info] downloading https://repo1.maven.org/maven2/com/typesafe/play/play-specs2_2.11/2.4.6/play-specs2_2.11-2.4.6.jar ...
[info]  [SUCCESSFUL ] com.typesafe.play#play-specs2_2.11;2.4.6!play-specs2_2.11.jar (599ms)
[info] downloading https://repo1.maven.org/maven2/com/typesafe/play/play-omnidoc_2.11/2.4.6/play-omnidoc_2.11-2.4.6.jar ...
[info]  [SUCCESSFUL ] com.typesafe.play#play-omnidoc_2.11;2.4.6!play-omnidoc_2.11.jar (104253ms)
[info] downloading https://repo1.maven.org/maven2/com/typesafe/play/play-docs_2.11/2.4.6/play-docs_2.11-2.4.6.jar ...
[info]  [SUCCESSFUL ] com.typesafe.play#play-docs_2.11;2.4.6!play-docs_2.11.jar (74391ms)
[info] Done updating.
[success] Total time: 261 s, completed 2015/12/24 18:20:37

real    4m42.231s
user    1m36.786s
sys 0m5.580s

もちろん「よし Scala 始めるか。とりあえず Play をやってみよう。」と思った人が最初にダウンロードする必要があるのは、この Play の jar ファイルだけでなく、最初に見た約 17 分かかった sbt ダウンロードに加えて、この約 5 分間の Play のダウンロードということにはなるわけですが(ここの例では不要な sbt プラグインを削っているので activator で雛形を作るともう少したくさんダウンロードする必要があります)、Play 自体は依存ライブラリが多くないことはおわかりいただけるかと思います。

play-netty-server や slim-play でシンプルな Web アプリ

このような最低限の依存ライブラリだけで、シンプルな Play アプリケーションをつくれることを示すデモとして以下の URL が参考になります。

ここでは slim-play にならって以下のようなファイルを置いて sbt run してみましょう。

app/AppLoader.scala

import play.api.ApplicationLoader.Context
import play.api._
import play.api.libs.concurrent.Execution.Implicits._
import play.api.mvc.Results._
import play.api.mvc._
import play.api.routing.Router
import play.api.routing.sird._
import scala.concurrent.Future

class AppLoader extends ApplicationLoader {
  def load(context: Context) = new BuiltInComponentsFromContext(context) {
    val router = Router.from {
      case GET(p"/hello/$to") => Action {
        Ok(s"Hello $to")
      }
    }
  }.application
}

conf/application.conf

play.application.loader = AppLoader

すると、先ほどの依存ライブラリだけで http://localhost:9000/hello/fooHello foo がレスポンスボディとして返ってくる動作を確認できます。

このように Play が「大量の依存ライブラリ、設定ファイルの準備が必要としそうなフルスタック Web フレームワーク」というのは、あくまで「何となく Rails に似ていそう」というイメージからくる誤解であって、コア部分は実はかなり依存の少ないライブラリであることがおわかりいただけたのではないかと思います。

便乗して少しだけ宣伝をば

逆に言うと Play はフルスタックというにはあまりに機能が限定的であるだけでなく Future をベースとした実装スタイルを理解する必要もありますので、Rails の代替というニーズにはあまりマッチしないかもしれません。

もし、より Rails 的なものを Scala で探している方は Skinny Framework もぜひ評価してみてください。ちょうど Meetup を開催して Skinny の考え方についてもブログに書きましたのでそちらもぜひ読んでみてください。

まとめ

以上、簡単ではありますが sbt の初回起動で待たされるあの長い jar ファイルのダウンロード待ちの内訳について説明してみました。

現時点で有効な対応策としては activator の dependencies つきをダウンロードするか、(手前味噌ですが)それより多少サイズが小さい skinny-blank-app-with-deps.zip をダウンロードして一度 ./skinny run していただくと、このダウンロード待ちをショートカットできるようになると思います。

そして、以下の二つの工夫をすることで Scala 初心者の方もモチベーションを落とすことなく Scala を始めていただけるのではないかと思います。

  • (上記で説明したやり方で)最初に発生する大量の jar ダウンロードをササッとショートカットしてしまう
  • 遅いと言われるコンパイルも sbt ~compilesbt ~test のようにバックグラウンドでやらせておく

ということで、年末年始はぜひ Scala を始めてみてください。