Is it time to ditch Svelte, React, and VUE?
Almost every modern web application built these days starts with an enormous clusterf*ck of JavaScript on the front-end which literally replaces the entire browser viewport with a JS-rendered virtual DOM and consumes JSON via a REST API which is built as a separate (but tightly coupled) application. Sounds kinda crazy, right? Spoiler alert: That’s because it is totally f*cking crazy!
If you’re building a Single Page Application (SPA) like maybe the next Figma or Trello, then one of those tools might fit the bill perfectly. But if you’re building a Multi Page Application (MPA) like a typical e-commerce website or even something like Gmail, I’m here to tell you that using a SPA framework is likely adding far more complexity than it’s worth.
The trouble with SPA architecture
Using the server only as a “dumb” API means we can no longer easily rely on it to maintain our application state. So we’ve moved all that state management to the client, inspiring a whole new category of frameworks like Redux and MobX. And since we can no longer use the server for basic routing, new libraries like React Router and Page.js were created to simulate the natural routing functionality we used to get for free.
Authentication used to be trivially easy to implement with server-side sessions. With SPA architecture, we typically use JSON Web Tokens which are far more difficult to implement (and far easier to implement badly). Even basic form submission can no longer rely on the browser’s standard implementation of HTML to submit form fields based on their name
attributes. We're now required to bind
those values to a JS object and manage and submit that object "manually".
In other words, all this stuff we used to get for free, now requires quite a lot of extra work. But is it worth it?
How did we get here?
In the olden days, the web was simple. Your browser sent an HTTP request, the server sent a new document, and your browser dutifully rendered it to the viewport blowing away whatever was there before. This was a bit clunky, though. It meant that if you wanted to update just one little piece of the page, you had to re-render the entire thing. Then JQuery came along which made it relatively simple to update only parts of the page using AJAX without a full-page refresh and to build web applications which felt far more interactive and responsive — more “app-like”. But it involved a lot of imperative JavaScript and was hard to maintain. If you wanted to make something moderately complex, it didn’t take long before you had an unmaintainable rat’s nest of JQuery.
Then along came Angular, followed by React and friends with a radical new approach: What if we re-think the whole concept of a “front-end” not as a DOM sprinkled with JavaScript — but rather as a JavaScript application which ultimately renders a DOM. Let’s turn it upside down! And it worked brilliantly if what you wanted to build was a Single Page App. Sure you lost a lot of the simplicity of a basic client/server architecture with HTML on the wire. But it freed you to build a truly app-like frontend experience. This new approach was exciting — almost intoxicating. And before long, every greenfield project looked like a good candidate for SPA.
But user expectations for a modern, reactive website have also increased dramatically over the past 5 or 10 years. So building a “web 1.0” style application with full page reloads just won’t cut it anymore.
Modern UI without SPA
So how can we build a modern MPA website without using a SPA-frontend / REST-backend architecture, without writing 80,000 lines of crufty JQuery, and without a janky full-page refresh on every click like it was built circa 1999?
There’s a new crop of libraries designed to provide modern interactivity while working with the grain of HTML and HTTP — both of which start with HT for Hypertext. This is key. The web was designed with the idea of Hypertext going up and down the wire. Not JSON. New libraries like Hotwire, HTMX, and Unpoly allow you to swap out chunks of your DOM in a declarative way by adding HTML attibutes or tags to your markup — without writing any JavaScript yourself. For example, an “Add to Cart” button could send a request to the server which modifies the server-side state of the cart items in your server-side session, then send back two chunks of DOM which replace only the #cart-sidebar
and #cart-icon-badge
on the page. This can be done quite elegantly and with beautiful CSS animations too.
When we send HTML down the wire as God (aka, Tim Berners-Lee) intended, it turns out there’s a ton of stupid shit we no longer need. Things like client-side state management — the DOM is the client-side state. Client-side routers? Don’t be ridiculous. JSON Web Tokens? Server sessions are tried and true — and so much easier to implement. Our database queries become very easy too since we’re writing all our routes on the server-side where we already have secure, direct access to the database.
I wrote a simple ExpressJS-based framework to implement this style of architecture which you can check out here: https://sane.codepilot.com
Ruby on Rails Shines in 2022 (no, really!)
Like most modern web developers, I’ve long shunned Ruby on Rails as a legacy framework designed to build a style of monolithic web application which is no longer even relevant. But here’s the thing: If we’re using something like Hotwire or HTMX on the frontend, we can use anything we want for the backend. Since we’re working with the grain of HTML, ideally, we want the very best system for creating server-rendered templates. There really aren’t that many full-featured, batteries-included frameworks out there. The big ones are Rails, Django, and Laravel. There are a few others up and coming such as Phoenix based on Elixer and Buffalo based on Go. But Rails has a huge community, is very polished, and is honestly just a joy to work with.
But crucially, the latest Rails 7.0 released last December includes the incredible new Hotwire library for frontend interactivity. Hotwire can be used with or without Rails — but it’s designed to pair perfectly with Rails development and is baked-in by default. So believe it or not, in 2022, Rails may now be the perfect full-stack framework for building post-jamstack era MPA web applications with modern interactivity that works with the grain of HTML rather than replacing it wholesale with the clusterf*ck of JS we’ve come to expect on the front-end plus a whole ‘nuther app for the backend API.
Wrapping it all up
If the ultimate goal is to build modern MPA websites in a way that is fast, organized, and maintainable, then it’s worth seriously considering whether SPA/Jamstack architecture is really the right tool for the job. With the arrival of modern DOM-swapping interactivity libraries like Hotwire, HTMX, and Unpoly, we finally have a real, practical alternative to SPA which allows us to create modern, elegant interfaces that work with the grain of HTML meaning we don’t have to reinvent the wheel for basic things like application state management and form submission. So if we’re going back to server-rendered templates, then maybe it’s time to take another look at the reigning all-time champion of web frameworks, Ruby on Rails. Especially now that the brand new 7.0 release comes with Hotwire baked-in, Rails just might be the very best solution in 2022 for building modern Multi Page Applications.