ScalaJs: Javascript for heathens (Part I)

I have no idea of frontend development. I assume it. I’m one of those backend cavemen that refuse can’t get out of their backend cave. However, ScalaJs people have developed something that helps getting people like me closer to the frontend world.

iZcUNxH

ScalaJs: what’s that?

ScalaJs is a library that allows translating Scala code to Javascript. As simple as that. Besides, toward to frontend developers, it is easily integrated with the top JS libraries like AngularJS or React.
What can it offer then, appart from what JS does? Coding frontend using a strongly typed language.
49775773
Thanks this, I actually know what my expression returns (forget about null, NaN and magical results).
Even that it’s true that the ScalaJS optimizer generated a lot of boilerplate at the beginning, it has improved a lot the way it generates JS code.

My first ScalaJs project

From Scalera, we’ve hired a monkey tested ourselves the library and wanted to shate the main keys for introducing you to your first ScalaJs mini-project, based on canvas. You can find here the example project which we have used as template.

Setting up the SBT project

Once created the basic scaffolding,

scalajs-example/
  project/
    build.sbt
  src/main/
    resources/
    scala/scalera/scalajs/example
  build.sbt

We’ll have to add two plugins to our project (at project/build.sbt):

  • sbt-scalajs : It allows us invoking, directly from SBT, the optimization task that will generate the JS file from the Scala sources.
  • workbench : Developed by Li Haoyi , it’s a plugin that manages to deploy your ScalaJS project locally in a pretty simple way. Just executing SBT, it launches a web server at localhost where you can find your application deployed 🙂

Our file should like this:

resolvers += "spray repo" at "http://repo.spray.io"
resolvers += "Typesafe repository" at "http://repo.typesafe.com/typesafe/releases/"
addSbtPlugin("org.scala-js" % "sbt-scalajs" % "0.6.1")
addSbtPlugin("com.lihaoyi" % "workbench" % "0.2.3")

Some workbench plugin users have detected the need of adding those resolver due to certain issue.

Defining the build.sbt file

Appart from providing the project name, organization and so…

import com.lihaoyi.workbench.Plugin._
enablePlugins(ScalaJSPlugin)
workbenchSettings

organization := "scalera"
version := "1.0"
scalaVersion := "2.11.2"
name := "scalajs-example"

libraryDependencies ++= Seq(
  "org.scala-js" %%% "scalajs-dom" % "0.8.0",
  "com.lihaoyi" %%% "scalatags" % "0.5.3")

bootSnippet := "scalera.scalajs.example.Boot().main(document.getElementById('canvas'));"
updateBrowsers <<= updateBrowsers.triggeredBy(fastOptJS in Compile)

it’s necessary to enable the sbt-scalajs plugin and import workbench settings. Afterwards, we’ll add at the libraryDependencies each of the needed (scalajs-dom for easily performing changes over the dom; and scalatags that provides a simple DSL for writting XML/HTML tags).

In addition, we’ll add a couple of extra things:

  • bootSnippet : The snippet that points to the application main.
  • updateBrowser : At this line we’re trying to say that a (partial) web browser reset shall be performed every time the fastOptJS task is called.

Adding some Scala code

We’ve already created the SBT project that will conform the frame of our app. Let’s add then some Scala logic by adding the file src/main/scalera/scalajs/example/Boot.scala:

package scalera.scalajs.example
 
import scala.scalajs.js.annotation.JSExport
 
import org.scalajs.dom
import org.scalajs.dom.html
 
@JSExport
object Boot {
 
  @JSExport
  def main(canvas: html.Canvas): Unit = {
 
    println("Hello world!")
 
    val ctx = canvas.getContext("2d")
      .asInstanceOf[dom.CanvasRenderingContext2D]
 
    val width = ctx.canvas.width
 
    val height = ctx.canvas.height
 
    def run: Unit = {
      ctx.clearRect(0, 0, width, height)
      ctx.fillStyle = "black"
      ctx.fillRect(0, 0, width, height)
    }
 
    dom.setInterval(() => run, 1000)
 
  }
}

Appart from some imports, what really attracts our attention in this snippet is:

  • The @JSExports. They’re used for indicating ScalaJs which elements must be exported to Javascript, so they can be accessed somewhere else (any other JS script or even the HTML).
  • The println("Hello world!"). The million dollar question is, where will it be printed? In the browser’s console, amigos.
  • The ctx context represents the canvas selection that we’re going to use.
  • The run method cleans the canvas surface, select the ‘black’ fill style, and paints a rectangle on the canvas surface.
  • dom.setInterval(() => run, 1000) : It causes the run method execution every second.

We’re almost done…

Some HTML hurts no one…

Ok, how do we visualize the awesome application we have just created? We’ll have to create an index.html file, as simple to be able to invoke our main method.

Let’s create such file at src/main/resources with the following content:

<!DOCTYPE html>
<html>
<head>
 <title>Scalera Scalajs-example</title>
 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
</head>
<body style="margin: 0px">


<div>
 <canvas style="display: block;padding:0;margin:auto;width=800" id="canvas" width="800" height="600"/>
</div>


<script type="text/javascript" src="../scalera-scalajs-example-fastopt.js"></script>
<script type="text/javascript" src="/workbench.js"></script>
<script>
 scalera.scalajs.example.Boot().main(document.getElementById('canvas'));
</script>
</body>
</html>

As you can see, the only thing that the HTML does is declaring a canvas and import 3 scripts:

  • ../scalera-scalajs-example-fastopt.js : The JS file generated from our Scala sources.
  • /workbench.js : script that loads the workbench plugin.
  • An anonymous script that loads the Boot object (exported to JS by using the @JSExport tag) and executes the main method providing the canvas that we previously declared.

Demo

To prove that our project works, it will be enough to execute sbt over the project’s root folder, and the workbench plugin will take care of launching the web server.

We’ll be able to access http://localhost:12345/target/scala-2.11/classes/index.html url and will see, at first place, that there’s a wonderful black rectangle that fulfils all the canvas; and, on the other hand, if we open the browser console, we’ll see printed our rocking Hello world!.

Ok, what about cons?

Despite of the amazing look of our example project, we’ve found some difficulties when coding it. And we have to mention them (just to avoid the feeling of tricking you):

  • Using Scala dependencies: ScalaJs cannot use classes/objects of dependencies that don’t have a ScalaJs project nature as well. It’s quite limiting but it makes sense if you think about the idea of ScalaJs being able to export to JS all involved Scala source code with a @JSExport tag.
  • Testing : ¿ScalaJS and Scalatest together? Hard to believe. But take a look at uTest

Conclusion

ScalaJs rocks. We don’t mean that it’s better than natively JS development, but it helps indeed that total frontend heathens get closer to this world that provides a lot of possibilities.

At future posts, we’ll see some examples about how to use CanvasRenderingContext2D or about how @JSExport tags work.

Peace out! 🙂

Anuncios

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s