The ideas I’m about to dump here are not new. I came up with them 4+ years ago (and it probably was not unique to me), but I coined a term for my formulation of it: middle-end. That link redirects you to a series of posts I wrote back then exploring my ideas. I also gave about a dozen conference talks in the same time period.
It’s 4 years later, and I still think we haven’t even begun to scratch the surface of what I hope(d) we’ll eventually get to. And worse, we now have a bunch of hollow buzzwordy hype around a new term (which I really hate): “isomorphic JS”. Why do I say “worse” and “hollow”? Because none of the discussion around isomorphic JS is even remotely addressing the true potential, and also because the term itself doesn’t even make much sense.
It’s like buying a famous novel and having a discussion about the contents of the copyright page inside the cover.
Let me give a glance at what I mean by “middle-end” (want more detail? see “what exactly is the middle end?”).
All web applications have certain tasks buried in various depths of their server-side back-end, tasks such as templating, URL routing, (stateless) data-validation, data formatting, header management, resource packaging, etc. Depending on your framework or platform of choice, these tasks are usually inextricably woven into the bowels of back-end code.
While this duplication between server and browser sucks, it’s far from the worst part of common web architecture.
These tasks require intimate knowledge of the unique challenges of client-side functionality, which only gets more complicated the more diversity we see in client devices, from phones to tablets to laptops to glasses to watches.
The middle-end architecture I’m suggesting insists that server-side JS (probably in node.js) is the best (not the only, of course!) way to implement these tasks.
Server-driven apps have the drawbacks that they can’t fully take advantage of the capabilities of the client. Client-driven apps (SPA’s) have the drawbacks that they discard any substantive role/capability of the server beyond REST APIs, which means they are entirely bound by the capabilities of the client, limited or advanced as they may be.
And there’s plenty more drawbacks on either side which I won’t waste effort re-counting.
So what is “hybrid”?
The middle-end lets us leverage the best of both sides, and minimize the drawbacks. We can render on the server or in the client with exactly the same code. We can validate incoming data on either side with exactly the same code. We can route app logic on either side with exactly the same code.
In short, code is hybrid when it lives neither only on the server nor only in the browser, but in both equally.
Hybrid apps are apps that live on the middle-end, which straddles the gap between server and client, and in most respects attempts to abstract and erase the boundary. They let the client do what it does best (interact with the user) and the server do what it does best (track & persist state). And everything in between, they let both sides divide up the work as necessary.
The initial page request to a hybrid app is fielded by a server-side JS middle-end that routes the request as appropriate, consults the back-end for any state or data (whether that back-end is JS or not), and then uses templating to formulate an appropriate full-page response.
Once that full-page response populates the client, the front-end begins to load up the appropriate bits of middle-end machinery so that the client can take over rendering (templating), validations, etc.
Hybrid sites/apps give us the best of both worlds, but with simplicity that beats either alone.
But we still haven’t begun to explore what hybrid apps can really do. Hybrid apps need to become what I call “Adaptive”.
Most apps that bother to do any kind of feature-testing to control how the app will behave do so only once, at the beginning of the interaction. This is far too limited.
An Adaptive app instead constantly monitors how it behaves, and adapts itself to ever-changing conditions.
As one example (there are many more!), an adaptive app could render the initial page response on the server, then begin rendering the rest of the pages in the client. But what makes Adaptive really powerful is monitoring how well it’s behaving/performing, and adapting as necessary.
When the page loaded, the device might have had full battery and strong radio signal. But now, the device is low on battery, so the CPU is throttled back, and so is the radio signal. Now, the rendering of UI elements on the client is not performing well. It’d be better for the app to switch back to server-side rendering, with less frequent requests.
Luckily, an adaptive hybrid app can do that without breaking a sweat!
The power of adaptive hybrid middle-end design is that it erases the lines between client and server, so there’s just one middle-end code base, and it runs however it needs to, wherever it needs to.
The picture is not all roses for adaptive hybrid apps. I see two main hitches that keep us from fully realizing this capability.
- “Client Hints”
One key necessity of erasing the boundary between browser and server so adaptive hybrid apps can shine to their full potential is that the server-side of the middle-end has to be able to make all the same sorts of decisions about client capability as the browser JS can do.
Right now, that’s only possible in hacky ways like user-agent string parsing + huge guesses, or extra round-trips where JS beacons detection results back to the server, or other exotic craziness.
Client Hints is a fledgling idea to send information to the server, such as client screen metrics (DPI, etc). The primary motivation seems to be to enable “responsive design”.
But I think this falls way too short. We must have the ability to let a server signal to the client all the same things that the client would detect for itself to make proper rendering decisions. That is the only way a server-side middle-end can adequately handle the client-side load when necessary.
Let’s advocate standards and browsers to fix the barriers that are holding back the middle-end. Let’s make apps that realize the power of server and client working together as one unified delivery platform. Let’s make web applications, not just browser or server applications.