Our thoughts, knowledge, insights and opinions

Scala in the browser. Getting Started with Scala.js

Scala.js

What is Scala.js?

Scala.js is compiler that targets JavaScript, unlike the traditional Scala compiler which targets JVM bytecode. What it means in practice - with Scala.js you can write Scala code that will be executed in the browser.

When Node.js first appeared, it’s selling point was the ability to use the same language for backend and frontend development. It was realized by using the same language to write backend code. This idea was heavily criticized. Many people claimed that if we want to strive for a single client and backend language we should pick the better one and in their opinion JavaScript was not the one.

Scala.js goes the other way around - it takes backend language and compiles it to executable JavaScript. Effectively extending Scala programming concepts to the web. Now, with Scala.js you can use all the Scala tricks you learned in backend to create Web apps. Of course, the strict compiler and advanced type system are definitely in place, so you don’t have to worry about ReferenceErrors, coercion or undefined variables.

Pitfalls

There are also things Scala.js cannot do. As the JavaScript runtime strongly differs from that offered by the JVM, some libraries written for the JVM won’t run in the browser. Most importantly Scala.js is unable to run Java code (say goodbye to Joda time) and libraries using reflection under the hood will fail (for instance many serialization libraries). Fortunately it’s not as bad as it seems. There are many Scala.js-compatible libraries available. For a more detailed description of the issue look here.

In this post we will create a simple app to help you with getting started. We will see how to code page using HTML and styling it using CSS, also fetching and putting some interactions in place as well.

Getting started

The fastest way to get started is to clone the barebone template created by Sébastien Doeraene. It does not provide many features out of the box, but it takes care of the configuration so you can move straight to the fun part. We will add changes there to make it fit our requirements.

[build.sbt]

A few things to notice here - we commented persistLauncher out, added scalatags as a dependency, and renamed the app. persistLauncher is a handy flag that lets us use an auto-start script. We don’t need it here. In this case I would prefer to make Scala.js build an executable JavaScript class and then I will start it manually. For your simple app we added scalatags library. I found this one to be very useful. It allows us to build HTML structure in a type safe manner. It’s a huge improvement over strings. The last thing is to change the name.

As we changed the name, we have to update the HTML file too:

[index-fastopt.html]

The important part here are the <script> tags. First of all we pull scala-js-organizer-fastopt.js in. This is the runnable file Scala.js is building via sbt. That’s why it’s located in target directory. The name of the script consist of name from build.sbt and a “-fastopt” suffix. The second script tag contains the actual entry point of our application. The call is built as follows: it starts with package name, followed by a call to an exported class and the exported method with client side parameters. It might sound a bit complicated at this point, but the confusion will go away after we inspect ScalaJSExample.

What is fastopt?

You might not have noticed it during backend programming, but Scala standard library is quite big in terms of code size. It’s not a big deal when doing server-side programming, but on mobile and web the size of the executable is a huge issue. Scala.js tries to give you best of the both worlds - provide you with the whole power of Scala standard library while also producing a small executable. To make the code small for production environments Scala.js makes heavy use of minification and dead code elimination. Unfortunately, the whole process is time consuming and makes the turnaround time longer. That’s why Scala.js has two build ‘modes’ - fast-opt for developer builds and full-opt for production machines. In this post we will use fastopt only.

Now let’s take a brief look at ScalaJSExample

[ScalaJSExample.scala]

Having this in place run sbt ~fastOptJS and open index-fastopt.html in a browser.

Basic App

As an example we will build a TODO app. Let’s keep try to keep it simple - it will be able to track tasks and count the time needed to finishing them. Nothing fancy, but it will demonstrate how to use Scala and JavaScript features together.

Tasks will be represented as

Let’s use scalatags to build an UI.

The snippet above creates the UI for our TODOs. For now it doesn’t really do anything. We will add interaction later on.

Remember about adding @JSExport annotations to methods you want to be accessible on the client side.

Adding Interaction

Until now, the template is static. Let’s wire it up with some logic. The easiest way to do that is to create an UI element, turn it into a node via render() and then attach callbacks. Like this

[ScalaJSExample.scala]

As you can see attaching a callback is really straightforward. The only thing you need to remember is that Scala.js is using assignment operator to attach events and that it is a mutating operation.

What about something slightly more advanced? Like time counter? In order to do that we will tap into the frontend - we will use wrapped JavaScript functions and classes together with Scala code. Consider this snippet:

[ScalaJSExample.scala]

Above we used the browser’s native setInterval function to schedule calls to refreshTimeSummary and inside that callback we use JavaScript’s Date class. It’s all glued together with Scala - we use partial application, foldLeft and string interpolation.

With Style

Having the dynamic and static parts in place, let’s make sure it looks decent. I’m no CSS/design expert so for me (and probably many of you) the best option would be to work together with a designer. Or use a battle-proven library like Bootstrap.

Bootstrap

Bootstrap offers a set of ready to use and decent visual styles. You can use it easily with your Scala.js code. Just assign classes to your elements. It’s simple as this

[ScalaJSExample.scala]

class is a reserved keyword in Scala, so remember to use ticks `

You can also do styling yourself using inline styles. Scala.js helps you with that by adding few useful constants. We can use both ways of styling in tandem.

[ScalaJSExample.scala]

Another option is to use ScalaCss. I didn’t try it myself, but at first glance looks promising.

My organizer looks like this

Organizer

Fetching Data

Firebase

Now we are able to show, add, and delete tasks stored locally, but we want more - we want to grab external data and add it here. Scala makes working with async code easy and Scala.js allows us to use this power for handling AJAX.

For this example we are going to use Firebase, but it can be any service of your choosing.

Let us start with adding a serialization library.

[build.sbt]

Now we can import necessary components

[ScalaJSExample.scala]

Having that in place calling an external service is really easy:

[ScalaJSExample.scala]

Summary

The example project we wrote above is pretty “low level” comparing to other TODOs. It’s more of a starter or playground for beginners, than a full tech demo. We can do much more here.

The same goes for Scala.js. The library itself forms a base on which more advanced frontend applications, frameworks and libraries can be written. In Scala! I can’t wait to see that.

As we’ve seen Scala.js is an interesting project and is getting more and more attention. In the world where the browser is becoming the main platform, Scala.js is a viable alternative for JavaScript. It doesn’t fix all the issues with frontend programming, but clears out at least one problem - the buggy lingua franca of the web - JavaScript.

I’m looking forward to see how this project will evolve in the future.

PS. As you can see from the source code Scala.js doesn’t necessarily save us from the real killer - complexity. We will explore how to fix that in the next post.

You like this post? Want to stay updated? Follow us on Twitter or subscribe to our Feed.