Menu

Guest Post - Elm: React Without Compromises

04 April 2017

This article was originally published on appendTo and written by Pete Lyons. appendTo offers Web Development and JavaScript training for teams.

The world of front end development has been experiencing a major paradigm shift over the past few years. Frameworks have shifted from Model/View and Object-Oriented paradigm of Backbone, Ember, Angularjs v1, and dozens of similar smaller projects to a new paradigm embracing immutable data structures, virtual DOM, and functional programming. The primary catalyst for this has been Facebook's React framework powered by the large budgets Facebook poured into engineering and advocacy, and perhaps seizing the opportunity created by the delays and rewrites associated with Google's AngularJS v2 framework.

React brings a hybrid ideology to the table combining virtual DOM and functional-style components (pass in state, get a rendered DOM result). But beyond that, React itself leaves a lot of paradigm and architectural questions open: state management, effect processing, mutability, etc. Thus some teams that want more functional programming concepts land on a stack of stateless React views, immutableJS data structures, and Redux for state change and application architecture. Within this stack, you are still ultimately coding in JavaScript and can use Flow for type annotations.

If those concepts click for you but you want something more coherent, have a look at Elm. Elm has been around (initially as a PhD Thesis) since 2012 and represents some of the core ideas adopted by React/Redux in a more thorough and integrated way by providing a new programming language that directly integrates these concepts.

With Elm, you get a strongly-typed functional programming language that compiles to JavaScript. An expressive type system allows the compiler to automatically detect many categories of errors such that they can never make it into a shipping Elm application. Elm has immutable data structures and pure functional semantics baked in. This is how it can offer a lot of guarantees about program correctness and also helps it achieve great virtual DOM performance. The strength of the type system enables large scale refactoring of your application without regressions.

So what constitutes an Elm application? First, there are no separate HTML templates and JavaScript code modules. The core library includes an Html module with a composable, functional API for representing a DOM tree. Each HTML element is a function taking a list of attributes and a list of children. These nest naturally so it ends up looking almost like HTML but with direct access to the power of a real programming language. That means your attribute values can be computed by a function, and lists of children can be processed with familiar functional programming list paradigms like map and filter. Ultimately your HTML is represented as a function that takes model data as input and returns the DOM structure as output. This model is composable, scales nicely, and deals well with complexity.

To build application behavior, Elm introduces the "Elm Architecture" where application actions such as clicking on a button, entering some text, or an AJAX response arriving are represented as strongly-typed events. These events (called Messages in Elm) are passed to a central update function whose job is to look at the current state, apply the logic appropriate for the current action message, and return a modified state for the application. This new state is then passed to the view function to render a new DOM tree, and virtual DOM can then efficiently update the real DOM.

This architecture has developers smiling as debugging and bug reproduction become much more consistent and tractable (although the type system prevents many bugs from shipping at all). One of Elm's killer demos early on was the "time-traveling debugger" where you can navigate backward and forward in the history of application states and observe how the UI changes. This is made possible by the design tenets of the architecture.

Elm ships with a core set of libraries for both key language-level functionality for dealing with data structures as well as basic web application building blocks for HTML, HTTP, and JSON. On top of that, the community contributes packages that can be plugged into your application via the Elm-package tool.

The Elm community is much much smaller than the mainstream React community, and probably always will be. The main corporate sponsor of Elm, No Red Ink, is many orders of magnitude smaller than Facebook. However, there are many active collaboration points including Slack chat, Github, Facebook groups, twitter accounts, blogs, and books. There's a detailed guide to the community resources below.

Elm is a great tool to sharpen your functional programming chops and it provides a much more pleasant and forgiving experience than other typed functional languages such as Haskell, largely due to Elm's simpler types and extremely high-quality compiler error messages. At the moment, it is probably not mainstream enough for corporate projects in technology-conservative workplaces. However, it is in production use and can be great for side projects and as a learning tool. The techniques you learn and master in Elm can directly benefit how you write JavaScript in general and React/Redux as well.

Interested in learning more about Elm and exploring a bit? Here's some key resources.