vmunier/sbt-web-scalajs

Help with applying this to use scalatags instead of Twirl; sbt workflow support for scalatags with Play

jbweeks opened this issue · 4 comments

Firstly, thanks for your contribution to the community!

Anyway, I am new to scalajs and scalatags, and am looking to migrate a Play application to use both scalatags and scalajs instead of Twirl and javascript.

I started down the road of following your example (split project into server, client, shared, etc.), only to realize the example and plugin were geared toward Twirl support.

Any pointers for scalatags instead of Twirl? I am pursuing a full-scala stack with no direct html or javascript. From what I can see based on playing with your example so far, is that I need a way to put the artifacts (scalajs) that will run on the client into a package that the server-side generated pages can include.

My expected execution for an example page would be:

  1. Browser request to Play server
  2. Play server Controller method authenticates request
  3. Play server serves page built with scalatags that includes scalajs "script"
  4. Browser receives page with embedded scalajs (built via scalatags), and executes scalajs main
    ...

The sbt workflow would have to put "client" artifacts into a place where they can be served much like other js (e.g. jquery)

Thanks!

Hi @jbweeks,

The sbt-play-scalajs plugin does not depend on Twirl, you can absolutely use the plugin without Twirl.

Also, do not include the play-scalajs-scripts library if you do not want to include the Scala.js scripts via Twirl.

To show you what play-with-scalajs-example would look like if it used ScalaTags instead of Twirl:

  • Delete app/views/index.scala.html and app/views/main.scala.html
  • Edit the server's libraryDependencies in build.sbt to add ScalaTags and remove play-scalajs-scripts
libraryDependencies ++= Seq(
-    "com.vmunier" %% "play-scalajs-scripts" % "0.3.0",
+    "com.lihaoyi" %% "scalatags" % "0.5.2"
  • Update app/controllers/Application.scala to something like:
object Application extends Controller {
  import scalatags.Text.all._
  def index = Action {
    Ok(indexView(SharedMessages.itWorks).toString).withHeaders(CONTENT_TYPE -> MimeTypes.HTML)
  }

  def indexView(message: String) = {
    val body = Seq(
      h2("Play and Scala.js share a same message"),
      ul(
        li("Play shouts out: ", em(message)),
        li("Scala.js shouts out: ", em(id := "scalajsShoutOut", em))
      ))

    mainView(body)
  }

  def mainView(content: Seq[Modifier]) = {
    html(
      body(
        content,
        // include the Scala.js scripts that sbt-play-scalajs has copied from the "client" project to the Play public target folder
        scripts("client")
      ))
  }

  def scripts(projectName: String) = Seq(selectScript(projectName), launcher(projectName))

  def selectScript(projectName: String): TypedTag[String] = {
    import play.api.Play
    if (Play.isProd(Play.current)) {
      script(src := s"/assets/${projectName.toLowerCase}-opt.js", `type` := "text/javascript")
    } else {
      script(src := s"/assets/${projectName.toLowerCase}-fastopt.js", `type` := "text/javascript")
    }
  }

  def launcher(projectName: String) = {
    script(src := s"/assets/${projectName.toLowerCase}-launcher.js", `type` := "text/javascript")
  }

}
  • Done, you can run the application again
$ sbt
> run
$ open http://localhost:9000

Hi @jbweeks,

Did the above points helped you using ScalaTags instead of Twirl?

Yes, worked perfectly. Sorry for the delay, got pulled onto other issues. Thank you very much!

If someone is interested, I've created a template from what @vmunier has described, adding the use of scalatags on the scalajs side as well.