A look at the current edge of web development; the Re3 Node.js stack

Although we work mostly with WordPress here at Avidmode, we also develop for Node.js from time to time (i.e. at any given opportunity). Lately, we’ve really been digging into the Re3 stack, so let’s talk about that and how it compares to the old PHP/MySQL combo.

Node.js

Whilst JavaScript runs in every browser, each has its own engine responsible for doing so. In Google Chrome, that engine is called V8, arguably the fastest of them all. However, V8 was designed from the ground up as a separate engine that can be integrated into almost anything. So, one night, a certain developer got angry enough at Ruby’s EventMachine and decided to make something new.

Now, a number of years later, Node.js is considered mature enough to run in a production environment. In short, it’s just a way to run JavaScript on the server, but it exploded into the largest open-source development community the world has ever seen. The package manager for Node.js, npm, has evolved into the package manager for JavaScript itself.

Unlike the stateless PHP, Node.js has a stateful event-based execution model, commonly known as asynchronous, which is fancy talk for saying that it keeps everything loaded in memory instead of starting from scratch with every HTTP request. Because of this, it’s also perfectly suited for the new WebSocket protocol which allows two-way communication between browser and server. It turns a website into something closer to an app.

A number of libraries and applications have popped up to take advantage of the asynchronous web, and three of them have gotten together to form the Re3 stack: React, Redux and RethinkDB.

React

Facebook has some of the most demanding UI of any website, so it follows that they would be the ones to come up with the best way of doing it. Enter React, developed in 2011 and open-sourced in 2013, it has since grown to the most popular JavaScript UI library and one of the most popular open-source projects overall.

It’s built around the sad fact that the DOM is slow (the DOM, or Document Object Model, being the browser’s way of rendering HTML into something you can see and interact with) and thus runs its own calculations to avoid touching it as much as possible. Because of this, developers no longer have to worry about changing individual components and can write code as though it was stateless, like back in the good old days.

Add to that a convenient way of compiling HTML-like syntax into vanilla JavaScript using JSX (JavaScript meets XML) and you’ve got a library that has conquered the V in MVC (and is making threatening sounds towards the C, too).

Redux

Inspired by the similar library Flux, Redux is a single-object immutable state container. This means that an application’s entire state (i.e. the data that’s kept in memory, like the current user, forum or blog posts) is stored in a single immutable object.

State changes are triggered by dispatching actions rather than making any direct interaction with the state data itself. In essence, you tell the state container what should happen and it responds based on what you’ve told it to do beforehand.

As the state changes, your web components receive the new data and React figures out what changes need to be made to the DOM as a result. This flow pattern, Redux -> React -> DOM, mirrors the ease and comfort of writing stateless applications where everything is loaded from scratch on every pageview and the data always flows in only one direction.

RethinkDB

Named “rethink” because of how asynchronous web development requires you to think differently, RethinkDB is designed from the ground up for asynchronicity and horizontal scaling.

Not unlike how the server can send data to the browser using the WebSockets protocol, RethinkDB allows you to listen to a query and receive changes as they happen. These changefeeds are perfectly suited for live updates, like those of a chat or forum application, removing the need for polling or pings that only mimic true live updates.

Secondly, a RethinkDB instance can be split into multiple shards with the data distributed amongst them, requiring no changes to your application logic. If your application’s load increases, just add more shards, and RethinkDB will handle all of that for you (with some rather minor configuration).

The Re3 stack

Together, we have this dataflow: RethinkDB <(Node.js)> Redux -> React -> DOM. Each client’s Redux store listens to changes from RethinkDB (via the server-side application logic in Node.js) and updates its state and DOM accordingly. With each HTTP request, the server renders the initial HTML (using ReactDOMServer) and sends along the initial state data. From that point on, the client opens up a WebSocket connection and enjoys fully asynchronous dataflow.

Dropping RethinkDB?

Redux and RethinkDB serve the same purpose on different sides. As some Redux evangelists would suggest, we could use Redux on the server, too. It’s all JavaScript, after all. However, I see two primary reasons why that would be a bad idea.

Persistence. The Redux store is kept in memory, which means it expires once the application exits. Similarly, you lose all your data if it crashes. If your application stores user data and content, you would need to synchronise it to some kind of persistent data store, at which point you might as well just use a database.

Cluster compatibility. Node.js has a beautiful cluster mode which allows your application to spread out over multiple processes that receive HTTP requests in a round-robin fashion. (Paired with pm2, this is an absolutely wonderful API solution.) But each process has its own Redux store, which means you would need to synchronise states between processes, an extremely arduous and complicated task.

Moreover, I can’t help but think that RethinkDB is server-side Redux. Redux’s own creators proclaim that its only purpose server-side is to set up the initial state. And if you were to add persistence and cluster compatibility to Redux, you would end up with RethinkDB, albeit written in JavaScript and thus slower than a native C++ application.

If your application requires neither data persistence nor cluster compatibility, by all means, stick with some neat isomorphic Redux solution. But don’t throw the baby out with the bathwater.

Re3 vs. WordPress

Now, with all the awesome and exciting benefits of an Re3 Node.js stack, why is the web not quickly abandoning old-world solutions like WordPress and getting on the full-stack JavaScript train? Well, it could, one day. But it wouldn’t happen because of technological advancement.

The way I see it, web technology reflects its purpose. Whilst websites have changed drastically over the last few decades, there’s at least one aspect of them that hasn’t budged; most of them are still stateless.

Think about it. You browse from page to page, blog post to blog post. They may be generated using a small mountain of code and a few hundred database queries, but you’re still looking at individual pages, displayed on their own, one by one.

Why would the technology backing a website need to be stateful if the website itself isn’t?

All that said, once the web does decide it’s time for a change, Avidmode will have already moved on. Because there’s another fact that shows no sign of changing.

Working with PHP is still like wearing lead shoes.

All the best,
Dan

Comments