VS.
I've been involved with full-stack development for a while now, especially stacks involving single page apps. When choosing to go with a single page webapp the backend concerns change. While any backend will do the job (think ruby, python, java, etc.) more emphasis is placed on the front-end stack as most of the time is spent in Javascript and less in the backend language since that is not where the UI logic resides. This is liberating in some senses as it allows one more freedom as language deficiencies become less of a problem. You don't have to decide between a language based on how you like the backend html templating or framework, since that is no longer involved. Think python tornado templates, JSF, or jade, three drastically different templating choices. But none of that matters when going with a single page app in the browser.
My goto server for a while has been Node.js for a great many reasons including the easy sharing of code and modules across the server and UI with Webpack or Browserify, first class asynchronous support, consistent language environment, and NPM, one of the best package/dependency managers, in my opinion, that exists.
Last year, however, a coworker encouraged me to give Scala a try, and so down the rabbit hole I went. I've come out with a somewhat mixed opinion but we'll get to that. Let me first go through the positives of the experience. While Java is a perfectly practical language, and it has a long history of solid mission critical usage, once you begin to dabble in other languages and language features, Java syntax begins to pale in comparison. Java 8 and 9 will begin to address some of those syntactical shortcomings, and there are alternatives like Jython, Jruby, Groovy, Ceylon, but one of the more prominent JVM languages in the industry has been Scala.
Scala is a drastic shift in mindset and approach even compared to Java and especially compared to developing in Javascript. There is a very different mindset with Scala given the available language constructs. Implicits open up a bit of a magical world, case classes and pattern matching encourage you to write highly structured code. Case classes themselves are a great benefit over potentially nothing in Node.js in terms of self-documentation. While some don't like Options I think they are more or less brilliant and a great way to handle None or Null values. The next best experience has been the existential operator (somevar?) in Coffeescript, however that is a very simplistic comparison. Scala has first class asynchronous and concurrency support. While the syntax is initially very difficult, let me say that again - very very difficult - I've found it surprisingly close to Coffeescript in quite a few respects, and that is a good thing. Scala allows you to write highly expressive yet compact code, more so than other languages.
Enough praise of Scala though, let's get to the differences in the experience of writing a backend in Scala vs. Node.js. Do remember this is a comparison between the development experience between a backend in Scala and Node.js, I am not considering other languages in the comparison, other languages which may have other various pros and cons.
Scala
- Strongly Typed - I can't emphasize how this ultimately feels like a breath of fresh air when developing a backend. I could say the same of Javascript with no syntactically defined types with rapid prototyping, but then experience development with typing and case classes and there is no mystery in what the database is returning or what fields you have to operate on.
- Pattern matching - Once you become accustomed to this construct, you will want to use it, most everywhere you can. While Javascript has the standard if/else and switch statements, and those do operate in a similar fashion, there is little I've encountered that has the raw power of pattern matching in Scala.
- for/yield - Once you get accustomed to for and yield in Scala, you wonder how you lived without it. Node.js gives you the EventEmitter and promises, and while those do clean things up considerably, they can't touch the power and conciseness of for and yield in Scala.
- Concurrency - Scala provides access to Akka which opens a whole new world of opportunities for the backend. Also being on the JVM provides a great deal more APIs for creating and handling threads and processes. Not something you would typically do directly in many webapp backends but there if you need it.
- JDK Interoperability - While Scala can't necessarily compete with Node.js with NPM or the number of active repositories on github, Scala does have access to any java library, and that is a major point. Want to use commons-lang, go ahead, or jOOQ, why not. This is a very compelling reason as there are certain libraries that are simply better in Java. Think the Salesforce API for example, or any RESTful API where you can generated a typed API access layer through a WSDL.
- ScalaJS - Due to the overwhelming feedback I've received in the community with this post I included ScalaJS as a benefit to going with Scala as a backend. ScalaJS may very well be the killer reason for allowing you to go with a full Scala stack. This effectively matches the functionality of a full javascript stack with Node.js but you get the type safety and power of the Scala language.
Node.js
- It's all Javascript! - First, calm your negative reaction, that is meant to be a positive statement. It's all Javascript means one can choose a module bundler like Webpack of Browserify to unify the backend and frontend environments. Being able to develop modules that are used in the backend and browser is a very nice ability. What is the most important here is the ability to use npm modules in the browser. At least ones that don't rely on the filesystem or ones that have been browserified. Do note that this functionality can be achieved through ScalaJS as well. With Scala you can unify your environment in a similar way, so this may come down to a matter of personal preference.
- Number of Packages - This warrants a strong consideration depending on the application you are creating. If you take a look at http://githut.info/ the language with the top active repositories, over 300k, is Javascript, Scala comes in at around 10k. Make no mistake, there is pretty solid coverage for just about anything you want to do with Scala, and Typesafe themselves has created a great deal of production quality libraries, but in terms of third-party, Javascript is hard to beat.
- Documentation, Articles, and Stack Overflow - Looking at the amount of content of what is on the web pertaining to these two languages, I found a great deal of difficulty many times finding a solution to certain problems I was having with Scala as I encountered issues. While there is definitely a growing repository of knowledge out there, I found myself also relying on people I could talk to directly who had experience with Scala. This is a bit in contrast to Javascript or other more popular languages where the net is flooded with problems and solutions and tutorials and techniques. The Scala community just isn't anywhere close to a language like javascript, or even Java for that matter.
- Asynchronous Libraries - Nearly every database or io library you need is asynchronous out of the box, or can be made so with promisification. This is the case because of the nature of Node.js. The landscape isn't so well defined with Scala. Given certain backends in Scala can be written with a thread per request model then it is fine for an API call to block, that means not every database API library is asynchronous. Some of them are forked to be asynchronous and labeled as experimental. While they may work fine, the point being you aren't as nearly guaranteed to have an asynchronous library when you find the functionality you need. When if you do find a forked async library, it may be labeled experimental. In my experience I never ultimately had a particular issue finding what I needed in Scala in terms of async libraries, but the availability isn't so well defined.
You'll notice in the above list that my reasons for liking Scala are primarily language specific, and my reasons for liking Node.js are primarily practical in nature. I believe this is a very important difference. While the Scala syntax can be cryptic and infuriating at times, I want to love it, there is a beauty in the syntax and language constructs Scala provides (After you accept the gray hairs). And I believe it is those constructs, combined with the strongly typed system, that attracts me to Scala as a backend, and makes Scala a very compelling alternative to the Node.js backend world. Like any language, you can likely use either language cover the gamut of possible apps you want to create, there will be little you can't do in either language (save more complicated concurrency), so part of the consideration then becomes experience, feel, and stylistic approach these languages use and how they feel to you as you develop in them.
Node.js still has a strong draw to me despite the benefits of Scala. I can't imagine how one could rapidly prototype in Scala any faster than in Node.js (or other scripting languages). Node.js is quick to setup, quick to compile and restart, package management just works, and there are very few gotchas. Depending on the size and scope of a project, Node.js has a much lower threshold of entrance in terms of resource requirements across the spectrum. The flip side to this is the larger any Javascript app grows, the easier it is for that app to derail unless a structured and solid design is followed. With Scala, you are going to have a much more structured basis to not only refactor but to avoid a possible rabbit trail of spaghetti code. Good and bad code can be written in any language, that said, it is easier to write bad code in certain languages than others. This may not be an issue for some people whatsoever, but Scala does provide the language constructs to write cleaner code in the long run. I personally have no issue particularly with Javascript in this regards; I'm well versed and comfortable with Javascript, but Scala is so much nicer to deal with in this regards. One answer to this for Node.js may be ScalaJS or Typescript.
My ultimate conclusion from being exposed to Scala as a backend RESTful server is that if you haven't experienced what Scala has to offer, then I wholeheartedly suggest you do. 'Antiquated' Java syntax has turned away many Javascript/scripting devs off for a while, but Scala is gaining steam and momentum, maybe not as fast as Node.js is, but it is here to stay. Learning Scala will only make you a better Javascript developer in the long run, and having the ability to choose between the two backends will provide you with much greater sense of freedom.
Last updated: November 1, 2023