It would be an understatement to say that Relay, GraphQL, Falcorjs, and other up-and-coming technologies have revolutionized how I think about building user interfaces. I’ve been doing a number of experiments to explore how we can build applications with the ideas of these tools, even without access to their implementation.
Relay, GraphQL, and Falcorjs all aim to generalize a solution to data fetching and updating. The ideas of REST have been tried, tested, and pushed to the limits. While they have numerous, well-known benefits, they are a database/model-centric view of the world. In today’s device landscape, the view is a much more difficult land to maintain and support for any length of time. These approaches flip the API layer from being model-centric to view-centric where the view dictates what data it requires and the shape that it should be in.
Below is a brief introduction to what the first experience has entailed and some predictions on what this means for the future.
Sure, there are a few success stories like Airbnb with Rendr and Yahoo! with Mojito, though these previous efforts haven’t taken hold in the community. The fact that all of the tools and frameworks being created have a hard dependency on the DOM hasn’t helped, either.
At a minimum, to have isomorphic views, one needs to be able to run purely in JS, output and update DOM structures (for the browser) and HTML strings (for the server), and needs to interoperate with Node/iojs’s module system.
Historically, we’ve attempted to keep the structural, presentational, and behavioral aspects of our web UIs isolated through the arbitrary technological separation of concerns.
The React team came on the scene with the idea of “rethinking our best practices.” React took this approach to our UIs by marrying behavioral and view concerns together. The React team has also been rethinking application architecture and the MV* paradigm that is so prevalent. They have introduced Flux, which, like MVC, is an architectural style or idea. Whilst MVC has always been pitched to me as a way to segregate concerns to build more maintainable applications, in practice, there always ends up being tight—and typically unclear—coupling between the pieces. In my experience thus far, Flux embraces this inherent coupling and offers up a way to organize responsibilities with a directed path through your codebase. Namely, for every action that can take place in your application, it must go through a central dispatcher which informs your data stores of what took place. It is then up to your stores on how to change and inform the view that something changed.
For a better introduction to Flux, I would highly recommend the following slides by Jeremy Morrell in addition to the primary Flux documentation.
Whether you choose a verbose implementation or something that hides away some of the boilerplate, the result is a very predictable and understandable system.
At Skookum, we create user personas for each client project. Historically, these personas have lived in a shared document as unceremonious blobs of text. My colleague Rob Luke has recently been working on a prototype for displaying these personas in a rich and interactive environment. This is a simple application involving a single list and detail view.
I spent the first five hours of my experiment day building this prototype with React. Architecturally speaking, this project uses react-resolver, react-router, and facebook’s flux dispatcher to handle isomorphic rendering. Rendering our HTML on both sides of the HTTP divide is fairly simple with these tools. Below is a slightly out-dated variant of the node and web entry points we are currently using:
The ideas and learnings from this and a few other projects are culminating in our isomorphic react application generator.
So we’ve proven that we can write the same codebase to power client and server rendering.
Next, I wondered if I could reuse any of the code from the web implementation to create a React Native application. React Native has a strong view layer already, so I wanted to experiment on the data access and flow layer. I started a new React Native application and referenced the Flux folder from the previous project into it. It was astounding having no previous iOS experience and only needing to spend an hour and a half to have a NavigatorIOS component connected to a list and detail view. The exact same Store and Action code that was powering the server and client DOM rendering implementation was powering the native application!
The View-Driven Future
The “write once, run anywhere” dream, though appealing, is a mystical unicorn. The two primary motivations for “running everywhere” is cost (money, time, effort) savings through code reuse, and audience reach. Although we are able to “write once, run a lot of places” on the web, we are forced to make numerous trade-offs to get there. React has the potential to greatly reduce the cost associated with specific implementations for multiple platforms.
My prediction for the next major evolution in the UI engineering world is that models will become view-centric. RESTful APIs are a great utility belt, but carry a cost of lost flexibility. To build scalable, maintainable systems we need to push the decisions of both data required and the shape of it out to the edges of our system—our users devices.