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…
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.
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.
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.
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.
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.
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.
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
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,