In the article, Tom goes on to explain how applications rendered on the server-side are clumsy when it comes to responsiveness. This is a fair point, server-side rendered applications typically rely on the PRG (POST-Redirect-GET) pattern. They have HTML
POST some data, the server processes the request, responds with a redirect to another page, and the client
GETs that other page. These are pretty much the basics of the web. What’s worse, as Tom notes, is that as you start adding AJAX calls to this server-side rendered content, you are now a slave to both state (what you initially pulled from the server) and behavior (users clicking on things) when it comes to updating the UI. That is the ultimate nightmare of a web developer.
And so the story goes…
The answer to a productive and maintainable web development orientation, that also favors customers, doesn’t lie in one or the other, but rather in the combination of both approaches. In this article, I’ll explore what all of this means.
Angular, Ember, and React
I hope 2015 is the year where we take out “dedicated client-side rendering” like Angular’s from our metaphorical best practices grab-bags. React and Ember are doing a good job of bringing people to their senses when it comes to one-sided rendering.
I’m not sure how the initiative to move Ember to shared-rendering, FastBoot will work, but if it hijacks
React is more of a “shared-rendering” native citizen, which makes it friendlier when it comes to progressive enhancement. It’s shared-rendering capabilities used to be mostly an option for Node.js developers, but Facebook recently revealed
react-native as a way to write native Android and iOS applications on React, making it even more appealing as it now enables cross-platform development, a lot like how Google shares code across platforms using j2objc.
The web is not native, though. React and Ember don’t hinder our ability to develop a progressively enhanced application, but they don’t exactly encourage it either. I’d call them — along with Angular — client-first frameworks. Client-first doesn’t encourage progressive enhancement. Quite the contrary, client-first actively discourages progressive. That’s a real problem.
These frameworks are nice and definitely boost our productivity, but we should never stop thinking about building applications in such a way that they’ll actually work well (not just render well) for people on slow or intermittent networks.
I think these last few months we did a good job of thinking critically about whether the Angular way is the right way. I’m convinced that the web would be a far better place if we developed most applications in a content-first manner.
<form> elements to allow users to interact with the site, it enables more parts of the core experience.
Suppose you have a TODO list. Checking items off would just be a matter of clicking on them in a client-first application, then the changes would be persisted in the background. In contrast, a server-first approach probably would’ve had a
<form> with the TODO list and some sort of Submit button. Right? But what if each TODO item was a
<form>? What if each of them was a
<button> within its own
<form>? Then you could have almost the same functionality as people have come to expect from client-first applications, but in an entirely progressive way!
The HTML would look like this, except with proper form
hrefs, and CSS classes for styling.
<ul> <li><form><button>This is an option</button></form></li> <li><form><button>This is another option</button></form></li> <li><form><button>This is yet another option</button></form></li> </ul>
That’s the main argument against not using your fancy frameworks, right? But they’re so productive! Well, using HTML and PRG is fast, too! You just forgot they even existed.
Sure, the PRG pattern is “slow”, and client-first is perceptively faster — but guess what? Upgrading an HTML-PRG experience into an AJAX experience is a matter of writing a few lines of code, if it’s done right. From there, turning the experience into a real-time experience is the only challenge left. And, honestly? That’s just a matter of listening for the appropriate events and responding to them!
A Server-First Web
Taunus is a server-first shared-rendering MVC engine that prioritizes content and encourages progressive enhancement. It’s what this blog runs on top of, it’s what the documentation mini-site runs on top of, and it’s what I’m using in Stompflow — pictured in the screenshot above, but yet to be released.
Being server-first has its perks as well, just like client-first does. For instance, I maintain email templates using the same templating engine that I use on web views. Being server-first also means that I don’t have to worry about state vs behavior as much, because I have the same views on both sides and I can re-render them at any time in the client-side.
You no longer fight against the disgrace IE8 unleashed onto you, but embrace it. You now fight against the idea that you should cram every single new feature onto users on old browsers.
Server-first is non-commitment to client-side technologies. With Taunus you don’t have to pick a client-side data-binding library, but you can choose to do so. We already agree that it’s easier to deal with vanilla components than jQuery plugins, or Angular directives, or React components, or even Web Components.
So, why not use a framework that empowers you to work this way? Using modular components that aren’t tied to the framework itself, which is more of a glorified “stay-out-of-the-way router” that dictates you how to do shared rendering by convention.
Fine, Taunus is tied to a server-side technology: Node.js (or io.js!)
That’s not an issue for React, or Ember. Not even for Angular.js.
But you know what? That’s a good thing.
Because you are forced to commit to a server-side technology first.