It has been a few years since Scala started its rapid expansion as a mainstream programming language for server-side application development.

In early 2016, Scala.js, a transpiler that translates your Scala code into (as claimed) highly performant and optimised JavaScript, has been announced to be no longer in experimental.

Therefore in this blog I will briefly introduce a few reasons why you should consider using Scala.js for your next project and will present some potential concerns you should keep in mind.

Scala, a JVM based language, is widely complimented by the conciseness of its syntax, balanced mixture of Object Oriented Programming and Functional Programming paradigms and the default preference of immutable objects.

As a result, the code-base is easy to reason and therefore complements asynchronous, referentially transparent systems.

You get Scala

And with that come all Scala perks – type inference, case classes, traits, objects, generics, pattern matching and implicits. ES6, of course, is an improvement to pure JavaScript - it gives you modules and some functional paradigms and with TypeScript you can also get strong typing - that is better than nothing! Let’s play a game – without looking up, what result would you expect from the following line?

["10", "10", "10", "10"].map(parseInt)

Answer: [10, NaN, 2, 3]    (not very obvious, is it?)

You can get good libraries that do stuff properly, but you must be careful not to transform your project into a snowflake.

Reusable domain and Isomorphism

Scala libraries, such as Scalaz or Shapeless, can be used with Scala.js and cross-compiled to JavaScript. Therefore, you can use not only all JavaScript community contributions, frameworks and libraries (such as Angular, React Native or jQuery) but also Scala and therefore Java! Probably worth noting that only pure Scala and Java libraries that do not depend on JVM specifics or system layer will compile to JavaScript.

Bring functional programming to web

That leads to the main point – you can share your server-side libraries with client-side (and vice versa). Share your libraries, skillsets and developers - it is like node.js but on steroids. The ability to cross-compile the code to JavaScript encourages developers to write pure and loosely coupled domain logic which does not depend on a particular technology or libraries.

Compiles, packages, optimizes, tests

You can ditch your crazy Grunt or Gulp compiler and produce a production eligible build with native Scala.js release plugins. It also gives you options to integrate Google Closure Compiler which after analysing the compiled JavaScript will remove any dead code, rewire syntax for better performance, warn about potential pitfalls and finally compress it.

Stronger IDE support

Some modern IDEs are able to infer types, precompile and highlight errors for dynamic languages, such as Python or JavaScript. However, have you ever tried to click-to-jump on a method or field and then got navigated to completely irrelevant code block?

In dynamic languages IDE tries to search through all your code-base and guess where the property is defined - due to that it can also often misreport error highlighting. With statically typed languages your IDE will verify the correctness of your syntax, types, arguments and parameters even bad programming choices such as non-tail-recursive code.

DOM typing

Call me old-school but I do not like mixing in DOM with JavaScript. Despite all the benefits of Virtual DOM I like the separation of responsibilities - makes it easier to reason. Nevertheless, Scala.js comes with DOM types meaning build your view hierarchy with strong types!

Interoperability

Scala.js is fully interoperable with JavaScript in both statically and dynamically typed way. Some frequently used frameworks provide statically typed Scala.js ports, such as Angular or Bootstrap or libraries, such as momentjs or d3. Unfortunately, the number of those statically typed facades isn’t large. Solution - Scala.js allows you to write dynamic code.

For example, you can say

val document = js.Dynamic.global.document
val playground = document.getElementById("playground")
val newP = document.createElement("p")
newP.innerHTML = "Hello world! <i>-- DOM</i>"
playground.appendChild(newP)

This is, however, a step backwards from the main benefits of Scala.js! But I guess it’s nice to have an option for the edge case scenarios. And yes, you do not need npm anymore – you can manage your dependencies with sbt and webjars

Massive development environment

At first, it might sound off-putting that you must download a huge development kit that includes Java JDK, SBT and Scala.js dependencies. But then again - not many back-end developers object to using Java just because they now must download 200MB JDK.

With increasing processing power and user demands for rich and offline-first applications, the browsers should be able to handle more complex applications that might indeed benefit from the proven software tools and practices.

Heavy Build Size

Even with Google Closure Compiler and native optimization, a hello world .js project would weigh around 100kb. It is, in fact, the base Scala standard library that is quite thick. This might be a burden for mobile devices with slow internet speeds.

On a flipside, many powerful web applications these days come packed with random libraries making the final build exceed 1MB. The end point is that if your domain codebase is small and the file size matters, then it might be a problem.

Learning curve

Scala and its development environment might be challenging at first. It is often considered as one of the languages that are hard to master due to it being influenced from abstract and algebraic functional programming.

It is indeed something to consider if you have never written a large and scalable server-side application before and are not sure the best practices to orchestrate your domain.

Just to compare the syntax, let’s write an example which will filter map of people by their age and create a list of their first names.

TypeScript

const personMap = new Map<number, Person>([
  [10, new Person("Roger", "Moore")],
  [20, new Person("James", "Bond")]
]);
const names = new Array<string>();
for (const [key, person] of personMap) {
  if (key > 15) {
    names.push(`${key} = ${person.firstName}`);
  }
}

Scala.js

val personMap = Map(
  10 -> new Person("Roger", "Moore"),
  20 -> new Person("James", "Bond")
)
val names = personMap.map {
  case (key, person) if key > 15 => s"$key = ${person.firstName}"
}

At the end of the day

Whether to go with ES6, TypeScript, Dart or ScalaJS is up to developers as they have their unique features and use. At the end of the day, it’s not what language you use - it is what will make you achieve your goal faster while maintaining the core values.

ScalaJS compared to other transpilers

What do you think? Let me know in comments below!