ScalaでなんかWebアプリをガッと作りたくなったときにどういう技術を使うべきなのか?という話です。自分はこういうふうに考えてるけどな〜というのを知見としてまとめておこうと思ってこの記事を書いています。いやいやこっちのが速いでしょみたいな話題歓迎です。なんか忘れてたらすみません。
言語
- Scala3、と言いたいところだけど
- たま~に3使えないことがある気がしたりするので、手堅くやりたいときは2にしがちな気がする
- とはいえ、3使って困ったことあまりない
- インデント構文のせいでTAB押して補完してたのが動かなくなるみたいなことがたまにある
エディタ
- LSP使えるエディタならなんでもいい(自分はEmacs)
- ファーストチョイスだとVSCodeでいいと思う
- IntelliJは独自のプレゼンテーションコンパイラを使っているのでちょっと勧めづらい
ビルドツール
- sbtでいいと思う
- とりあえずポンでアプリ作るならsbtでいいのでは
- 情報量がとにかく多いのがメリット
- Millは単体で手堅くまとまっているので、小さなライブラリとかで使うかもしれない
テスト
- ScalaTest
- Specs2は一回使ったことがあるけどScalaTestをずっと使ってる
- Cake PatternでDDD開発してるとモック書きやすいと思うけど、Guiceを使ってDIしてもいいかもしれない?どうなんだろう?
依存性注入(DI)
- 自分はCake Patternを使いがち
- フレームワークを使う人も多いようだ
アーキテクチャ
- 普段Cake PatternによるDDDで開発してるのでとりあえずCake Pattern使いがちだが、もっと気楽なやりかたがあるかもしれない?
- しかしWebアプリは最終的に巨大な1つの泥団子になるんだよね
Webフレームワーク/サーバ
- 巨大フレームワークを許容するならPlay
- 軽量でいいならScalatra
- APIサーバが欲しいならhttp4s
を使うかな〜と思っています。
GraphQLが必要ならSangriaを使うけど、中規模なAPIでSangriaちゃんとうまく使いこなせるかわからない。サンプルがぜんぜんない気がする。
雑なWebアプリだとストリーミングとかいらなくて、だいたいはデッカいStringがもらえれば十分なんだけど、ライブラリは丁寧に作ってあるので手間暇かけないとPOSTのbodyが取り出せないみたいなことが割とある。かっこよく作ればかっこいいんだろうけど、とりあえずメモリに載せればよくない?みたいに考えがち。
テンプレートエンジン
- Twirl
- Playを使っているなら自動的にこれになるはず
- コンパイル時にごにょごにょするので、コンパイルしないと反映されないデザイナ泣かせ
- Scalate
- 使ったことがないけど軽量で良さそう
- Mustache相当の記法が使える
JSONまわり
- ファーストチョイスでCirceを使う。
- ScalaJS、Scala Nativeにも対応しているので勝手が良い
- デファクト(だと勝手に思っている)
- フロントエンドの一部をScalaJSで組むと全自動serialize/deserializeできたりしないか?と夢想してるけど、やったことない
- 必要に応じてMessagePackとかProtobufとかに手を出す必要が出る?
RDBMSまわり
- 基本的にORMとかあまり使わないので、ScalikeJDBCで素のSQLを書く。
- HikariCPでコネクションプーリングすると思う。
- RDBMSは使い慣れたMySQLを使うと思うけど、最近はPostgreSQLが気になっている
キューイング
- 非同期処理はCats Effectとかで扱ってもいいけど、Workerノードに逃がしたりとかしたいだろうからメッセージキュー用ミドルウェアをどこかで導入したくなると思う
- 仕事の都合でFireworqを使い慣れてるけど、Scalaだとなにが定番なんだろう
Auth
- Firebase AuthenticationとかのSaaSに任せたい。
- SHA256とかのダイジェストだとか暗号化まわりはJVMの機能を借りることになる。
- そのかわりNative対応とかができなくなったり面倒になったりする気がする。
- pac4j使ってOAuth2対応やったことがあるので、APIサーバとかもこれで認証かけられるはず
便利なツール
- giter8(g8)
sbt new user/なんちゃらら
でテンプレートが展開される。最近のライブラリはよくこの手のテンプレートでquick start / evaluationできるようにしている- オレオレテンプレートも使えるので、定番キットをあらかじめ設定したデッキを用意しておくと1コマンドで即戦力に。競技プログラミングのアレみたいな感じ
- ジーパチと呼んでるけど、僕だけだと思う
便利なライブラリ
- Typesafe Config
- 設定ファイルのライブラリ。
- Playで使われてたりと割と定番感あるけどどうなんですかね
- 僕はファーストチョイスで使います
- Catsファミリー
- 関数型言語としてのScalaを大幅に補強するライブラリ。他のライブラリもCatsと組み合わせられるようになっていることが多い。
- 高度な抽象化と合成の機能によって、結果的にボイラープレートが減るという形になることが多い。
- 関数型言語に対するある程度の造詣が必要になる。
- Decline
- CLIオプションパーサ。面倒になる前に使うと便利だがCats依存になる
- Akkaファミリー
- CQRSとかイベントソーシングとかやるなら必要になってくるけど、ライセンスが変更されたので本格的な開発をやるなら忌避してしまうかも。「覚悟」ができてるなら使うと思う。
- Shapeless
- データ構造をグニャングニャンする必要があるといった場合には必要になるかも。
- とはいえ、たいてい事前にデータ構造の型は固定できるはずなのであまりいらない気がする。
- os-lib
- OSのコマンド呼び出したいとか、一時ファイル作ったりするとかのOS雑務をやらせるときに使う。
- tapir
- 使ったことはない
- エンドポイントの定義自体を単体で切り出したライブラリ
- これをhttp4sとかOpenAPIのドキュメントジェネレータに与えていろいろ生成するっぽい
- おもしろそう
追記(2023-06-19): tapir使った。
ローカル開発テク
- ミドルウェアだけdocker composeで起動して本体はsbtを直に起動して開発しがち
- sbtは良くできてるので処理系ごちゃごちゃになって壊れたり、ライブラリがグローバルに混ざって壊れたりしない
- これが普通だろ
sbt-revolver
を使って自動リロード・自動サーバ再起動を行う
デプロイとか
- sbt-assemblyでJARに固めてHTTPサーバを起動する
- sbt-native-packager
- Docker Imageを生成したりネイティブイメージを生成したりできる便利なプラグイン。
- これでDocker Image作ってそのままデプロイすれば最短ルートな気がする
- GitHub Actions
- CIに使ったりリリースに使ったり
- Cloud Run
- Dockerイメージさえあればとりあえず公開できるのでAWSのECSよりも早いと思う
いかがでしたか?
いかがでしたかじゃねーよという話ですが、自分はよくこういうスタックでなんかを作ることが多いです。皆様の最強のデッキ、教えてください。