Recently when I started working on my startup, I needed to choose a set of technologies that will make our small team effective. From a high-level architectural perspective, our product is a fairly typical modern app: it has an API backend, a single-page web app, and mobile apps for iOS and Android. Having used Scala successfully for many years, the choice on the backend was obvious. But when it came to the frontend (web and mobile apps), we decided to use Scala through Scala.js as well. Given that Scala.js is a fairly new technology (the current version is 0.6.6), I had some trepidations on choosing it. A few months in, I am more than happy to have made that choice. So wanted to share what I find so attractive about Scala.js.
Scala.js in short
Things going for Scala.js
- React allows expressing types for properties. This feature is more like runtime assertions based on types. The guarantees offered by this feature is fairly weak and checking is late (during the actual execution in development mode), but it is a step in the direction that favors static typing.
- Flow offers static analysis through annotated and inferred types to show type errors during build time. Type annotations you can provide aren't as expressive as in Scala, but it can save you from a few hard to debug type errors.
- SoundScript aims to improve upon ideas in Typescript and Flow with a major focus on types.
- Even when not including types in the code itself, there is a tendency of being type aware at least in the documentation. For example, Falcor documentation describes types in great details.
Even looking at languages in general, it is clear that the need for static typing is being felt: Typed Clojure, Typed Lua etc. "Walks like a Duck, Quacks like a Duck, it must be a Duck" has changed to "If it is a Duck, just say so!".
All these point to a clear recognition that some form of static typing is helpful when developing complex apps. Scala's type system is far more expressive and battle-hardened, so it should allow leap-frogging other approaches. On a flip side: a few will look at Scala's type system as too expressive and/or too complex! And this isn't a facetious point. Static languages, Scala included, are still trying to find the right mix of ease of use and safety.
Static typing also is helping us with confidence in what we have built. As it is testing is hard. Testing frontend is even more so. While no substitute for proper testing, static typing has been helping enormously to offer some assurance even before we test the app.
Functional programming is gaining even more support in JS
forEach without needing an external library such as underscore or lodash.
Scala's functional programming support is far more comprehensive. One area of particular interest in frontend development--async programming--becomes very natural using
Promises in Scala. The mental model of mapping and flatmapping over futures is way more natural than callbacks all over the code base. Here too, JS world is moving in the right direction with APIs such as Fetch.
Scala is a bit uniquely positioned here in that it also combines object-orientation with functional programming. With ES6 including a proper support for classes, developers should get that familiar feel.
We have a lot of code that is best represented as data transformation and lends well to functional programming. Overall functional programming concepts have kept things clean, testable, and maintainable.
Immutability is starting to be recognized as a good thing
A few years back, frontend development meant mutating objects and responding to the changes. AngularJS 1.0, for example, relied on observing mutations in data and DOM and keeping them in sync through a two-way binding mechanism. This mutability-oriented thinking led to the
Object.observe proposal in ES7.
Object.observe ES7 proposal may not happen after all.
In our product, we use a modified Flux pattern and limit mutability to a few stores (we are considering switching to Diode). This reduces the cognitive burden tremendously, since we know where to look when things change or don't change as expected. As an immediate benefit of using immutable model, we get undo/redo functionality at virtually no cost.
For us, thanks to the incremental build support in Scala.js, each change takes about 5 seconds to build (on a year old Macbook Pro). While not too bad, this is something where Scala.js could improve upon and there are a few ideas being considered such an incremental linker that should cut down this time to a smaller number.
Scala.js already supports the isomorphism property
Isomorphism, in the context of webapps, implies having a choice of performing some work on server or client. For example, rendering the initial page on the server and then enhancing it in the client (with events handlers etc.) is a common way to improve the initial load time.
We utilize isomorphism to run the several algorithms on either server or client depending on the context. This allowed us to write a few fairly complex algorithms only once and have them run wherever they fit best--on the JVM backend or the JS frontend.
Scala ecosystem is behind Scala.js
There seems palpable energy in Scala community around supporting Scala.js. Basically, the Scala community is starting to see JS as the second platform for Scala. A few libraries specifically target Scala.js (upickle, boopickle, autowire, etc.). Those that focused initially on the only platform available earlier--JVM--are changing to make them work on the JS platform (Scalatest, scalaz, shapeless, monocle, etc.) where appropriate. New libraries see supporting Scala.js as a common requirement (cats, lenses, circe, etc.). This energy around Scala.js helps to apply the same set of libraries and techniques that worked well on the server side to the client side.
Is it the right time?
New programming languages, frameworks, tools, and approaches--however great--catch on only when the target audience is already ready for the goodies offered by them. For Scala.js, UI programming community seems primed to embrace many aspects available in Scala for quite some time now. All these factors make me feel that Scala.js could prove to be a formidable candidate when it comes to frontend development. Of course, there are many other factors that will play a role in deciding if Scala.js is going to actually succeed. It seems like a no-brainer for a developer already familiar with Scala to give a shot in trying Scala.js, but only time will tell if other developers will embrace Scala to use Scala.js.
As far as we are concerned, using Scala.js has been working wonderfully!