Elm vs. React: Development and Performance
We're going to look at:
- setup and installation
- the feedback loop during development
- the ecosystems of packages
- integration into existing codebases
The app we’re using for the comparison shows a grid of restaurants and loads more as you scroll. When you click on one, it gets added to a wishlist. This demonstrates rendering performance and how data flow works between multiple components. It was also large enough to show differences in the feedback loop during development.
Which is Easier To Get Started With?
Elm and React both give you the opportunity to try them out in the
browser, so you can learn their syntax and how they work
immediately. React's version of "try it out" is simpler, while Elm's version is a full-page code editor which has multiple examples
demonstrating the syntax, how to work with buttons, how to do drag &
drop, and some basic HTML5 Canvas examples. While React's version does
because the examples are better and the editor allows free-form
code to be written. There is also a new online editor for Elm called
Ellie that makes it even easier to try out right in the web browser.
Both Elm and React are installed using NPM, the Node Package
Manager. Elm is globally installed and provides its own package
manager. The default install of Elm includes the core libraries, HTML
libraries and the Virtual DOM rendering engine. The default install of
React includes React and the React-DOM library.
The React tutorial suggests installing create-react-app, which is a
way to get React up and running quickly. It does not include
Webpack or any other build tool, but it does let you use JSX syntax,
right into the Elm compiler.
Elm and React are easy to install and both have made efforts to
keep things as simple as possible. React gets a point here with its
officially endorsed create-react-app boilerplate project (though there
are boilerplate starter projects out there for Elm, too).
The Development Feedback Loop
While developing the app, I found React's starter kit nice to work with
recompiled whenever a change was made and the browser reloaded the web
page. Elm's equivalent is elm-reactor which also watches Elm files,
recompiles and reloads the web browser.
What give Elm an edge over React are the compiler error
messages. While Elm has better type-checking, and React does not have
any built-in type-checking (aside from rudimentary component
properties type-checking), comparing the error messages is another
part of the feedback loop.
Performance: Is Elm Faster Than React?
Blazing Fast HTML Benchmark
We ran the benchmark with React 15.3.1, Angular 2 and Elm 0.17
Here are the results:
The benchmark is a to-do list web app where items are added and then
removed in rapid succession. React is the slowest of the bunch at
4.875 seconds; Angular 2 is at 3.358 seconds, and Elm 0.17 clocked in
at 2.964 seconds. These are the optimized versions for each library,
and you can compare the code yourself to see just what optimizations have been made.
Packages and Libraries
Another point of comparison is the number of packages and libraries
available for Elm and React. We should also do a comparison
of some of the documentation and the general quality of the libraries.
React, being more popular at this time, has a wealth of packages and
libraries available. It doesn’t match the number of jQuery plugins out
there, but it's getting there. The idea of composable components that
have a one-way data flow is so intuitive, and React is so easy to get
into; it’s not hard to see why there are so many new libraries out
there, with cool new user interface components being created and
Elm's advantage right now in terms of libraries is that the people
writing them are early adopters who have experience with functional
programming and type-checking. Being used to the paradigm, they
can write higher quality code. The other advantage is that the number
of choices you have to make is smaller.
Because Elm allows type declarations, all packages come with a basic
set of API documentation based on all the type declarations for types,
records and functions.
Another advantage is that some of the major React packages are
included within Elm's core; such as Redux, Flux, Nuclear.js and
Immutable.js. There's no need to search for a reactive flow library or
immutable objects library when the Elm language includes those
features by default.
However, when we do an apples-to-apples comparison with React, we find
Elm falling short. Generally, we shouldn't judge the merit of a
language or framework based on how many packages and modules there are,
or based on popularity, but the simple fact is that React is popular,
and with more developers there are more bug reports and
fixes to the packages and more momentum in driving different modules
and libraries to be developed.
Integrating Elm or React Into Existing Code
React has only one way of being integrated into a code base: it can
only replace DOM nodes. This is great because it keeps things simple,
and when you're working on integrating React into an existing code
base, all you need to worry about is passing data from the rest of
the web app into the React components.
All the other nice things about React, like using Redux, Nuclear.js, Immutable.js and ReactRouter, can be integrated later on. React is
only one part of the framework and it can function as a replacement
for the view rendering of any other framework. You don't even have to
use the JSX syntax! You can start using React in an existing web app
by including the React and ReactDOM scripts and with a few lines of
Elm has three different ways to embed components and applications:
fullscreen, embedded and worker. Fullscreen replaces the page with
the Elm app, great for writing web-based games. Embedded mode
functions in the same way as React: it renders into a particular DOM
node. Worker lets you use the Elm component inside of a web worker, as
a background process that works with the rest of your app.
flags for one-way communication (similar to passing properties into a
React component), or you can use subscriptions to listen for events
from the Elm component, such as mouse clicks or text input changes
(similar to event callbacks in React). When we limit the comparison
between Elm and React to React's mode of integration, Elm is a bit
more complicated in terms of having to set up flags and subscriptions
but once you get used to it, it's about as easy as React.
What could give Elm an edge over React is the compilation and
bundling. You can compile multiple Elm components into one bundle and
then include a script tag and an initialization script, and voila: you
now have access to all of your Elm components in a nice convenient
package. Because it is built into Elm, you don't have to rely on
Grunt, Gulp, Webpack, SystemJS or whatever flavor of module bundler
and build system is popular today. However, since you have to learn
Elm as well, it can be a hard sell to integrate it into an existing
Conclusion: And The Winner Is...
Here's how Elm and React compare:
Setup and Installation: It's a tie
- Elm can be installed using NPM (Node Package Manager) and it has
its own package manager to make it simple to add more packages. There are Elm syntax highlighters for the popular text editors and IDEs.
- React can be installed using NPM and it doesn't need anything else. You can start using it immediately.
Development Feedback Loop: Elm wins
- Elm wins because of elm-reactor, a built-in way to create and test Elm components and applications rapidly
- React loses because it requires a transpiler for ES6, a transpiler for JSX, and it also requires webpack to tie it all together, which is a lot of setup just to get the development feedback loop started.
Packages and Libraries: React wins
- Elm doesn't have as many packages as React, and because Elm itself hasn't released a stable version 1.0, the underlying architecture of libraries could change with every new release.
- React wins because it has a large number of libraries, and many more components have been written with it due to Facebook's popularity.
Integration into Existing Code: React wins
- Elm almost wins because it has three different ways to integrate components, and all your components can be compiled into one
inside of the existing code base.
Ultimately, both frameworks are really useful, but they have different strengths. I hope our comparison here can help you choose which one is right for you.