LoginSignup
1
0

Scala3でScalaHTML, ScalaCSSを使う

Posted at

背景

Scala 3でWebアプリケーションを作成したい。
その際に、HTML, CSSもScalaを使って書きたい。

解決策

Scala 3 で ScalaHTML, ScalaCSSを使う。

ScalaHTML
https://index.scala-lang.org/yrichika/scalahtml

ScalaCSS
https://japgolly.github.io/scalacss/book/index.html

環境

Windows 11
Java: OpenJDK 17.0.7
Scala : 3.3.0
sbt : 1.9.0
Akka: 2.7.0
Akka-HTTP: 10.5.2

※1. Akka, Akka-HTTPについては、ライセンスがBSLなので、無料で使えるのは条件のある環境になります。Scala 3がサポートされているAkka-HTTPを使おうとすると、Akkaは2.7以上を使わなければならないので、必然的にBSLになります。

※2. これから導入するScalaHTMLの要件は3.0 >= Scala >= 2.13.5ですが、上のAkka-HTTPが3.0.0で動かないので、Scalaのバージョンを3.3.0にしています。一応、コンパイルは通ります。

導入

libraryDependenciesを更新する

libraryDependencies += "io.github.yrichika" %% "scalahtml" % "0.1.1"
libraryDependencies += "com.github.japgolly.scalacss" %% "core" % "0.8.0-RC1"

適宜、Seq()などを使って書き換えます。

ソースコードを作成する

適宜、プロジェクトの適切な位置にソースコードを置きましょう。
ScalaHTML

HTML.scala
package com.isageek.hakushimeita.xnote.client

import scalahtml.Tags._

object MyHtml {
    val html = html5() {
        "any string or tag methods here"
    }

    def render() = html 
}

ScalaCSS

Style.scala
package com.isageek.hakushimeita.xnote.client

import scala.language.postfixOps
import scalacss.DevDefaults._

object MyStyles extends StyleSheet.Standalone {
  import dsl._

  "div.std" - (
    margin(12 px, auto),
    textAlign.left,
    cursor.pointer,

    &.hover -
      cursor.zoomIn,

    media.not.handheld.landscape.maxWidth(640 px) -
      width(400 px),

    &("span") -
      color.red
  )

  "h1".firstChild -
    fontWeight.bold

  for (i <- 0 to 3)
    s".indent-$i" -
      paddingLeft(i * 2.ex)
}

※ オフィシャルなドキュメントには載っていませんが、import scala.language.postfixOpsが必要

Akka-HTTP
HTMLファイルを読み込むのではなくて、
先ほど作成したMyHTMLオブジェクトから、直接取得します。

Main.scala
/*
@main def hello: Unit =
  println("Hello world!")
  println(msg)

def msg = "I was compiled by Scala 3. :)"
*/

/*
 * Copyright (C) 2020-2023 Lightbend Inc. <https://www.lightbend.com>
 */

//package docs.http.scaladsl
package $package$.server

import akka.actor.typed.ActorSystem
import akka.actor.typed.scaladsl.Behaviors
import akka.http.scaladsl.Http
import akka.http.scaladsl.model._
import akka.http.scaladsl.server.Directives._
import scala.io.StdIn

import $package$.client.MyHtml

object HttpServerRoutingMinimal {

  def main(args: Array[String]): Unit = {

    implicit val system = ActorSystem(Behaviors.empty, "my-system")
    // needed for the future flatMap/onComplete in the end
    implicit val executionContext = system.executionContext

    val route =
      path("hello") {
        get {
//          complete(HttpEntity(ContentTypes.`text/html(UTF-8)`, "<h1>Say hello to akka-http</h1>"))
          complete(HttpEntity(ContentTypes.`text/html(UTF-8)`, MyHtml.render()))
        }
      }

    val bindingFuture = Http().newServerAt("localhost", 8080).bind(route)

    println(s"Server now online. Please navigate to http://localhost:8080/hello\nPress RETURN to stop...")
    StdIn.readLine() // let it run until user presses return
    bindingFuture
      .flatMap(_.unbind()) // trigger unbinding from the port
      .onComplete(_ => system.terminate()) // and shutdown when done
  }
}

実行

sbt run するだけ。
built.sbtの設定が不十分なのか、warningっぽいのが出るが、動くので今回は一応無視します。

image.png

出力されました。

予定

Scala.jsを使うので、サイトの構成はSPAにしたい。
フレームワークLaminarを導入したいところ。
なので、ScalaHTMLは導入しましたが、たくさん使うわけではありません。
index.htmlになるものを作って、お役目を果たします。
Akka-HTTPは今回の趣旨にあっていて、便利なのだけれど、ライセンスの関係で、プロダクトには開発ライセンスが発生するため、おそらく変えなければならない。いい代わりが見つかるといいですが…

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0