How HTMX allows you to build modern web apps faster and cheaper than bloated client-side SPA Frameworks
Date: 2024-01-26 | create | tech | htmx |
I've built dozens of projects over the years with technologies ranging from static-site generators to old-school MPAs to SPAs with React / NextJS / SvelteKit. For the past 5ish years SPAs have been the most popular way to build frontends with React coming out on top.
But I always felt like these SPAs were a bit too complex, a bit too tedious to setup for the simple things I was building. For the most part, all I wanted to do was build a simple web page displaying some data, with some controls (inputs, buttons, etc) for the user, and the ability to change based on those controls. These allowed you to do that but came with a bunch of baggage - lots of build tools and configuration, new ways of thinking ab and managing state, huge initial payloads w a bunch of lifecycle events.
It worked. But it felt bloated. A bit too complex and a bit too tedious to do simple things.
So when I stumbled on the HTMX / low-js trend last year I was immediately intrigued and have been intently following along, researching, and experimenting with these techniques. So far I've really enjoyed it and have gone so far as to start building my apps with low-js on F# instead of SvelteKit (my fave SPA framework).
I think it has a lot of potential for making modern web app development simpler, faster, and cheaper.
In the rest of this post we're going to explore how HTMX provides simpler, faster, and cheaper web app development vs SPA frameworks.
Most apps are simple CRUD
First it's important to come to a shared understanding that most apps are just simple CRUD with a few extra steps. Yes you've got some custom logic, yes you've got some cool views, and yes you've got some async stuff going on.
But largely (like 90%+ by my estimation) of apps (and certainly of codebase surface area) just does CRUD and then we've got some views we give to the user so that they can control / take action on our system.
This means that most UIs are really just doing this:
- Display some data (lists, tables, details)
- Provide some controls (inputs, links, buttons)
- Do stuff based on what the user does with the controls
- We're probably not building a video game that needs to simulate an entire world at 60fps (in which case go use Godot or Unreal or Phaser).
- We're not building the next photo shop (in which case go wild w your fave SPA or faster with wasm).
For the most part, we're just building simple web pages that solve some particular problem - usually displaying data to the user and allowing them to take actions on it.
So when we think about what we need to accomplish this, it's mostly an easy way to display data and add controls.
Modern apps are just sites that feel fast
SPAs became popular because they added some dynamism to web pages that wasn't easily achievable before. The old way of making sites was to have one URL that server-side rendered one HTML page (often called a Multi-Page Application or MPA). This meant that if something changed, the only way to get that new change in the UI was to do a full reload.
Full reloads are really annoying UX-wise!
- The screen flashes!
- We lose our scroll state!
- If we were filling something out (like a form) we usually lose all those inputs!
Plus they're often pretty slow cause they're reloading EVERYTHING even when we only needed to change a small value somewhere.
So we moved away from MPAs towards SPAs to make these interactions better for the user and for things to feel faster. We could update parts of the page based on their input and this happened quickly without erasing inputs or losing scroll location or flashing the screen. So UX was improved cause we could make our UIs more dynamic to user actions.
But when we think about the core value proposition - the problem the SPAs were solving and how - it's really that they provided a better user experience by NOT disrupting the user with full page reloads.
SPAs accomplish this improved UX but often comes with extra baggage that hinders it from improving further.
- Large initial SPA Payloads -> slower initial load times
- More complicated lifecycle / state management -> more bugs and fewer features
- Large data flow surface area to maintain / process (DB -> API -> SPA -> HTML) -> often slows down development and allows more surface area for bugs to hide
We currently see this as the status quo. This is how things are done so it's not a problem. That's just how things are.
HTMX allows partial page reloads making apps feel fast and modern
HTMX says there's another way we could accomplish this. We can achieve modern feeling apps by focusing on solving the core issue - don't ruin the user experience by forcing full page reloads to update data.
It achieves this by giving HTML elements the ability to request and swap out partial HTML pages. This means you get the modern feel with fast, dynamic pages because you can reload parts of the page quickly without affecting the rest of the page.
This is exactly what SPAs are doing - it's their core value proposition - but without any of the complexity. There are no build steps, very little to learn, and it's easy to gradually sprinkle into apps - it's all server-side rendered HTML with a few extra attributes.
So HTMX gives us everything we need to create modern apps without any of the baggage SPAs bring - thus modern apps simpler, faster, and cheaper.
Simple Systems Scale which is why I'm so bullish on Simple Scalable Systems. HTMX is definitely a Simple Scalable System.
In fact it's simple enough that it's highly composable and thus flexible. You can use it in any tech stack that can accept HTTP requests and return HTML (which is most stacks). This is where the HOWL stack comes from (HTMX On Whatever you Like).
I'm personally building fullstack apps with F# + HTMX, usually coupled w a small clientside library like Alpine for a little extra dynamism. It's been a lot of fun and has helped me build side projects faster and cheaper.
If you liked this post you might also like: