An Opinionated Overview of JavaScript Stuff (early 2015)

The next major version of a product at work is probably a rich/fat web client talking to a REST API, like many things these days. We are currently at the beginning of this transition. There is one small sub-system that has been rewritten in Angular (1.3 at time of writing) utilizing a legacy AJAX system we have, but before getting too much further along in our current path, I felt it was probably a good idea to survey the current landscape of web client frameworks/libraries/tools and get some stuff down on (digital) paper.

Now the discussion here is going to be biased by a couple things:

  1. My own personal preferences; I like strong statically typed, functional languages (e.g., Haskell)
  2. The needs at work. For the work situation, we need (in my opinion) something that is ‘simple’, not necessarily a shallow learning curve, but rather an execution model that you can understand, easy debugging and help making sure things don’t break. Another factor is the development team at work is pretty small, a couple to a few developers at any given time, so one person needs to be able to accomplish a lot and maintain the product over time; we need something expressive.
  3. I haven’t actually used most of these tools. I’m making judgments based on the project’s documentation and the chatter on other sites (HN, Reddit, etc.) from people who have used them.

It should go without saying, but the contents of my personal blog are my own opinions and in no way represent the opinions of my employer. Furthermore, I in no way intended or wish to misrepresent any of the tools in this post, if you find an issue, please get in touch.

Plain JS solutions

AngularJS 1.x

Homepage

AngularJS is a sophisticated framework for building web applications which emphasizes a bi-directional dataflow and testing. It’s one of the oldest of the ‘new’ JS libraries/frameworks and as such, has some inertia to it, though I feel it really only started picking up steam in the past couple of years.

Pros

  • Already working for a few things at work
  • Lots of drop in components
  • Two-way data binding
  • Backed by Google
  • Emphasis on testability
  • Fairly straightforward design patterns to follow (and published guidelines)

Cons

  • Can be complicated and fragile (we have already seen this at work)
  • Two-way data binding
  • Likely large and incompatible 2.x coming within the next year, maybe with migration tools, but likely to be a very different framework (i.e. knowledge/experience gained on 1.x may not directly translate into productivity with 2.x)
  • Can have performance issues

Flux + React

Flux HomepageReact Homepage

One of the newer kids on the block, React is ‘View’ layer for web applications which utilizes a ‘Virtual DOM’ to build up and swap out parts of the DOM efficiently. Flux is an application architecture (as well as the name of Facebook’s implementation of the Flux architecture) which emphasizes a uni-directional dataflow which works well with React.

Pros

  • One-way dataflow
  • Generally more performant (compared to AngularJS)
  • Backed by Facebook
  • Flexibility in implementation/architecture, Flux provides some structure
  • React Native

Cons

  • More immature ecosystem (compare to AngularJS)
  • No single best-practice/do-this architecture to follow, though Flux provides some structure

Misc

More info

Tools are available built around these components:

Mercury

Homepage

Pros

  • Extremely modular, can use which parts one wants/needs
  • Generally very good performance (in contention for title of highest performing library currently available I’d say)
  • Flexibility in implementation/architecture

Cons

  • Extremely modular
  • No single best-practice/do-this architecture to follow
  • No big corporate backing?

Mithril

Homepage

Opposite end of the spectrum from Mercury with regards to modularity: Mithril is one file. It’s goal is to be small and simple, both in the code itself and the cognitive load required to use it.

Pros

  • Very small and ‘simple’
  • Very good performance, up there with Mercury
  • Flexibility in implementation/architecture

Cons

  • I feel it could be a lot of boilerplate/lack of convenient functionality
  • No single best-practice/do-this architecture to follow, there are some official suggestions on how to structure an app, but you would largely be developing our your way to structure the code
  • No big corporate backing?

Typed JS tools

Plain JS will probably one day get type annotations1 likely based on whatever syntax/semantics Typescript and Flow can come to agree on since these are the two working tools (that I know of) that have the types sprinkled in otherwise vanilla JS syntax.

Typescript

Homepage

TypeScript is a superset of JS that gives developers a more familiar OOP syntax to use that compiles down to plain JS. It was one of the first typed JS supersets and also brings in ES6/ES 2015-like features (e.g., modules and classes). The forthcoming 1.5 release will bring the compiler to almost complete parity with ES6/ES 2015 and the 1.6 release will start pulling in ES7 features. It’s one of the best ways to get the JS-of-tomorrow today.

Flow

Homepage

A static type checker for JavaScript

Flow is practically brand new, just open sourced at the end of 2014, though Facebook has been using it internally for a while. All it does is type checking (unlike TypeScript) using annotations similar to TypeScript. From what I’ve seen Flow’s type system is a bit better and more expressive, though TypeScript is catching up (e.g. TypeScript 1.4 will include Union Types and Type Aliases, which Flow already supports).

The downside is that the code Flow type-checks has to be pretty much plain JS (with type annotations) so you can’t really combine it with other tools (like Sweet.js) unless those other tools will preserve the annotations when transforming the code. One could potentially work around this with something like flotate (some of it’s rationale discussed here) as long as the other tools preserve comments. Some tools (like Babel) already support Flow and I imagine that broader community support for type annotations will grow quickly.

Elm

Homepage

Note: When referring to Elm, generally I mean Elm + the elm-html package (which is a virtual-dom library similar to React).

Elm’s a modern language designed to make writing code for interactive applications short, fast, and maintainable. It’s well thought-out, pragmatic, and tries to structure it’s design so it’s easy to pickup/understand.

Pros

  • “Better” language than JS to work with
  • Many of the same benefits of Flux + React or Mercury
  • Interoperable with plain JS (via a language feature called ports)
  • Can have even better performance than React because of language features (immutable data structures, optional lazy evaluations, etc.)
  • Don’t have to deal with npm and bower while also getting some really nice tooling
  • A natural way to structure applications

Cons

  • Like React, more immature ecosystem
  • Needs a runtime in the browser

PureScript

Homepage

PureScript is a small strongly typed programming language that compiles to JavaScript.

Taking many cues from Haskell, but making them fit in the JS world (like strict-by-default evaluation), PureScript compiles down to a plain JS with no runtime (unlike Elm). It has existing bindings to things like React and Angular, though they are both in the alpha/experimental stages. They also push against some of the functional features of PureScript so using something lower-level and more friendly to immutable data like virtual-dom is probably a better approach.

Paired with something like the signal library and you have a virtual-dom FRP implementation to play with.

Pros

  • “Better” language than JS to work with
  • Flexibility in implementation, it’s a full-blown general purpose language so less choices are made for you, unlike something more focused like Elm
  • No (extra) runtime

Cons

  • Still somewhat experimental

Other Haskell Stuff

There’s a lot of awesome stuff going in the Haskell world to improve JS development, mostly in the form of Haskell-to-JavaScript compilers. As of today, most of it probably isn’t ready for prime time/big stuff, but is improving and I expect things to get a lot better here quickly.

See this post for a further discussion of some of these options and the reddit post has some good discussion.

Full Haskell

  • GHCJS - Version of GHC that emits JS instead of native code, compile any Haskell to JS
  • Haste - Compile almost any Haskell to JS

Haskell interop

Other

Other JS Language Tools

Sweet.js

Homepage

This is a macro system for JS. It would probably be extremely useful in cutting down boilerplate if one chooses to use plain JS-of-today for a project. The biggest downside with Sweet.js is that it doesn’t (yet) support type annotations so doesn’t integrate super nicely with the other static-analysis/type-checking tools.

Bacon.js and RxJS

Bacon.js HomepageRxJS Homepage

Both Bacon.js and RxJS provide “reactive” components, which, roughly speaking, are things that have some notion of time built into them. They use different terms, but I believe the libraries are fairly equivalent in functionally. The Bacon.js docs have a bit on their compatibility.

Immutable and Mori

Immutable.js HomepageMori Homepage

Provides immutable data structures. Immutable data is great for a variety of things and in particular in can be a big boon when working with rendering stuff since determining if anything has changed is a cheap check.

Babel

Homepage

Babel makes next generation JS features available now by compiling them down into today’s JS. The currently broadly supported JS lacks a lot of modern features, this can be a great way to utilize some of them (like modules) until the browsers/your user base catch up. Used to be called 6to5.

CoffeeScript

Homepage

I mention this merely because it is somewhat popular, but I don’t really consider it an option as it doesn’t bring a whole lot of important things (namely static type checking) that the other solutions provide, it is largely just syntax sugar.

Everything Else

There are a bazillion other JS frameworks/tools out there that I didn’t look at closely, some linked below:

Frameworks

Pieces

Languages

Other

TodoMVC Benchmark

There’s a TodoMVC benchmark with a variety of popular (and obscure) frameworks here:

http://matt-esch.github.io/mercury-perf/

The benchmark consists of creating 100 todos, marking them as completed, and then deleting them. It aims to give an idea of how frameworks perform under real-world-ish conditions running idiomatic code (as opposed to micro-benchmarks, which tend to take advantage of obscure tricks and aggressive optimizations that sacrifice maintainability for extra speed). A more limited benchmark, but with a prettier graph at the end is also available; it was put together for the blog post announcing elm-html.

Best Bets Today

Flux + React + Immutable + Flow

Integrating a static analysis tool like Flow would be a requirement for me, but that could be dropped if your requirements are pure JS with no build step (and/or you subscribe to the pulling your hair out and yelling at the computer style of debugging/refactoring; static analysis really helps people). I’d probably also want to use some JS-of-tomorrow layer as well, either using Babel or swapping out Flow for Typescript.

To see how some of this stuff plays together, see this blog post which suggests making heavy use of the PureRenderMixin (among other things) and generally having pure functions and immutable data. With the introduction of React Native, this setup has a lot of potential to reuse all the application-y bits (Flux + Immutable + Flow + (Babel)) and swap out the React bit for a native view layer.

Elm

A clean, modern language designed from the ground up to make web development better. Immature in some ways and may not be “production ready” enough for all cases, but well worth a look and experiment. The language is evolving fairly quickly, so you’ll need to keep up, but that’s no different that most other things in the JS world right now (^_^).

TL;DR

If you choose to stick with plain JS, look at Flux (Marty.js being my suggested implementation) + React and try to integrate some sort of static analysis into your workflow; I’d suggest Flow. If you have/are given more freedom, explore Elm. If you want something small and simple, look at Mithril.js.

The main take away is: buy what the functional programming folks have been selling for decades, pure functions and immutable data. You have to go out of your way to do this in plain JS; using a language that has this style of programming built in will cut down the boilerplate and open up nicer abstractions.

TL;DR the TL;DR

Learn Haskell.

I hope this was helpful in some way. Thanks for reading/skimming/skipping to the end.


  1. https://github.com/mozilla/sweet.js/issues/393#issuecomment-56405997