The client is not always right: another twist in modern front-end development (Part 1)

peibolsang

Pablo Bermejo

Posted on December 28, 2020

The client is not always right: another twist in modern front-end development (Part 1)

Well, in line with the rest of the year, the end of 2020 has been an incredibly eventful week for the Web development community, leaving us with major technology announcements. Chief amongst them, and almost simultaneously (I don't believe in casualties) we have to highlight both Facebook's React Server Components and Basecamp's Hotwire releases. While these two sets of libraries feature similar capabilities for building modern Web user interfaces, they do so from totally opposite approaches. And this is actually very good news as we are about to explain.

RSC and Hotwire provide the Web development community with new and better options for our ever-increasing use cases in the digital world. Of course, arriving at this type of consensus is not always possible without a bit of controversy (and sometimes online arguments) in an increasingly polarized world. And the reason is that these two technologies revived the old debate about where the Web UI rendering should happen: client-side VS server-side.

The Pendulum

It's not the first time that we hear this analogy that software architecture trends behave as a giant Foucault's pendulum, swinging back and forth between the most current and socially accepted patterns. And Web development is not an exception to that, swinging forth and back between client-side and server-side rendering approaches.

Let me try to visualize this idea with a picture

Software Pendulum

  1. Initial stage represents the early days of the Web when only a few people with host admin rights could build static web pages that rendered on the client (the browser). That was purely client-side rendering based on HTML and CSS, which soon started to fall short in a world where the users wanted to interact with real-time data through these Web interfaces.

  2. This is how we moved from Web pages to Web Apps. In an attempt to provide our users with the dynamic behavior they were demanding we moved the HTML generation closer to the data: the server. We came up with the MVC pattern in order to do that without coupling this view generation with the actual data fetching, and we brought all the major programming languages onboard (PHP, Java, .NET, etc...). But there was a problem: Web Apps were still behaving as Web pages and the navigation and user experience was suboptimal, especially for large applications.

  3. I still remember how we gradually started to move things to the client-side again. These were the old Web 2.0 days where we built Rich Internet Applications (this is how SPAs were called back then) leaning on the experience and lessons learned gained from the server-side rendering approach. Yes, we moved the MVC to the client. This allowed for a much better UX and a more desktop-like behavior, which was what our users were demanding. Javascript development exploded and the proliferation of hundreds of Web frameworks kicked off, establishing a new normal in Web development that still spans our current days. And as you can imagine, not without tremendous challenges: the complexity of developing and building SPAs with some of these frameworks has grown exponentially to the point that sometimes it is absolutely unmanageable, both from a physical (bundle size) and organizational (team size) point of view.

  4. And this is where things start to get interesting. Conscious of this problem, those teams who supported server-side rendering started to refine this approach based on the lessons learned from the pendulum's previous state. In other words, by leveraging all the good things about the client-side's smoother application navigation and user experience, while keeping the performance and efficiency of the server-side. Frameworks like LiveView or ASP.NET Blazor took this opportunity to make incredibly good improvements with respect to the server-side rendering state of the art. And this is the area where Hotwire is playing today. However ...

  5. ... Hotwire's approach may not be enough for the most UX-demanding Web Apps. In other words, managing UI state on the server and streaming that back to the browser via Websockets together with some Javascript sprinkles may not satisfy all the business requirements and user expectations for reactive user experiences and interaction-intensive interfaces. This is where React Server Components will sit tomorrow and I intentionally captured this as another pendulum's swing back to the client-side.

(Note that although Hotwire has been made available publicly this week it is production-ready since mid this year, and other similar frameworks have been around for a while, so IMHO it is far to say that RSC is Facebook's reaction to those technologies)

The Trade-offs

This is what all this is about. As Eric Elliot once said "Engineering tradeoffs and stupidity are often indistinguishable if you're unaware of the tradeoffs".

So which technology is better? It depends on your context.

Building Web Apps using Ruby, Python, Elixir, or Java that work well with minimal Javascript is perfectly fine. However, evil is in the work well detail, as the approach may not satisfy all UX expectations (more on this later). Also, if the team is able to leverage their existing backend skills and ship the Web App twice as fast and cheap as someone else who has a slightly better UX, that could be a good trade-off in a competitive market. That is definitely something to aspire to if you're trying to run a successful business. See, it depends.

We touched briefly on team skills but this is also very important. There might be some resistance to do everything with Javascript, so they can spend more time developing in the languages they know instead. Again, this would make sense for some use cases for Web Apps where user interaction is expected to be light. And I think this is where Basecamp wants to position themselves with Hotwire: the most important part of their message is that they want to empower small teams.

Let me be clear: hunting for simplicity is not wrong and will never be wrong. Not on my watch! But we need to be aware of the trade-offs. I tend to agree that "pursuing JavaScript for everything" as the default new norm could be harmful to our Web dev technology ecosystem. Again, there are no one-size-fits-all solutions.

Pure SSR comes with a trade-off. Typically you are sacrificing a bit of UX at the expense of lighter bundles. IMHO, the server-side approach will never be as good as the client-side when it comes to re-rendering the UI based on user interactions. When building some modern, reactive Web Apps with multiple user interaction and feedback points, there are things such as rendering race conditions or component cascade updates caused by a shared mutable state. React figured out how to solve this with deterministic view renders based on an immutable UI state. And, this is the important part, React manages action-based rendering as close as possible to the user: this is, the browser.

Even more, with the introduction of RSC the whole point is that there is no more render lock-in. There is freedom to move across the boundaries as our constraints change. Server Components are the mechanism that lets you do data fetching and run some logic without shipping it to the client at all. As Dan Abramov said "Rendering to HTML is still a useful optimization on top of the first render before Javascript loads".

So once again, on the flip side, building Web Apps using React with minimal backend code is perfectly fine. Also, if the team has a powerful Javascript background and the architecture supports this model, shipping client-side rendered web Apps with the user at the center and outstanding attention to UX details is a good trade-off.

(Continue reading Part 2!)

đź’– đź’Ş đź™… đźš©
peibolsang
Pablo Bermejo

Posted on December 28, 2020

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related