The current state of web application development
User expectations of the web are now that you have this super-smooth no-reload experience. Unfortunately, it’s an expectation that is usually delivered with single-page applications (SPAs) that rely on libraries and frameworks like React and Angular, which are very specialised tools that can be complicated to work with.
A new approach is to put the ability to deliver this UX back into the hands of engineers that built websites before the SPA-craze, leveraging their existing toolsets and knowledge, and HTMX is the best example I’ve used so far.
The costs of SPA
SPAs have allowed engineers to create some great web applications, but they come with a cost:
-
Hugely increased complexity both in terms of architecture and developer experience. You have to spend considerable time learning about frameworks.
-
Tooling is an ever-shifting landscape in terms of building and packaging code.
-
Managing state on both the client and server
-
Frameworks, on top of libraries, on top of other libraries, on top of polyfills. React even recommend using a framework on top of their tech:
-
React is a library. It lets you put components together, but it doesn’t prescribe how to do routing and data fetching. To build an entire app with React, we recommend a full-stack React framework.
-
By their nature, a fat client requires the client to execute a lot of JavaScript. If you have modern hardware, this is fine, but these applications will be unusable & slow for those on older hardware or in locations with slow and unreliable internet connections.
- It is very easy to make an SPA incorrectly, where you need to use the right approach with hooks to avoid ending up with abysmal client-side performance.
-
Some SPA implementations of SPA throw away progressive enhancement (a notable and noble exception is Remix). Therefore, you must have JavaScript turned on for most SPAs.
-
If you wish to use something other than JavaScript or TypeScript, you must traverse the treacherous road of transpilation.
-
It has created backend and frontend silos in many companies, carrying high coordination costs.
Before SPAs, you’d choose your preferred language and deliver HTML to a user’s browser in response to HTTP requests. This is fine, but it offers little interactivity and, in some cases, could make an annoying-to-use UI, especially regarding having the page fully reload on every interaction. To get around this, you’d typically sprinkle varying amounts of JS to grease the UX wheels.
Whilst this approach can feel old-fashioned to some, this approach is what inspired the original paper of REST, especially concerning hypermedia. The hypermedia approach of building websites led to the world-wide-web being an incredible success.
Hypermedia?
The following is a response from a data API, not hypermedia.
{
"sort": "12-34-56",
"number": "87654321",
"balance": "123.45"
}
To make this data useful in an SPA, the code must understand the structure and decide what to render and what controls to make available.
REST describes the use of hypermedia. Hypermedia is where your responses are not just raw data but are instead a payload describing the media (think HTML tags like
, headers, etc.) and how to manipulate it (like form
, input
).
A server returning HTML describing a bank account, with some form of controls to work with the resource, is an example of hypermedia. The server is now responsible for deciding how to render the data (with the slight caveat of CSS) and what controls should be displayed.
- Sort
- 12-34-56
- Number
- 87654321
- Balance
- £123.45
The approach means you have one universal client, the web browser; it understands how to display the hypermedia responses and lets the user work with the “controls” to do whatever they need.
Carson Gross on The Go Time podcast
…when browsers first came out, this idea of one universal network client that could talk to any application over this crazy hypermedia technology was really, really novel. And it still is.
If you told someone in 1980, “You know what – you’re gonna be using the same piece of software to access your news, your bank, your calendar, this stuff called email, and all this stuff”, they would have looked at you cross-eyed, they wouldn’t know what you were talking about, unless they happened to be in one of the small research groups that was looking into this sort of stuff.
Whilst ostensibly, people building SPAs talk about using “RESTful” APIs to provide data exchange to their client-side code, the approach is not RESTful in the purist sense because it does not use hypermedia.
Instead of one universal client, scores of developers create bespoke clients, which have to understand the raw data they fetch from web servers and then render controls according to the data. With this approach, the browser is more of a JavaScript, HTML and CSS runtime.
By definition, a fatter client will carry more effort and cost than a thin one. However, the “original” hypermedia approach arguably is not good enough for all of today’s needs; the controls that the browser can work with and the way it requires a full page refresh to use them mean the user experience isn’t good enough for many types of web-app we need to make.
HTMX and hypermedia
Unlike SPAs, HTMX doesn’t throw away the architectural approach of REST; it augments the browser, improving its hypermedia capabilities and making it simpler to deliver a rich client experience without having to write much JavaScript if any at all.
You can use whatever programming language you like to deliver HTML, just like we used to. This means you can use battle-tested, mature tooling, using a “true RESTful” approach, resulting in a far more straightforward development approach with less accidental complexity.
HTMX allows you to design pages that fetch fragments of HTML from your server to update the user’s page as needed without the annoying full-page load refresh.
We’ll now see this in practice with the classic TODO-list application.
Clojure HTMX TODO
First-of-all, please don’t get overly concerned with this being written in Clojure. I did it in Clojure for fun, but the beauty of this approach is that you can use whatever language you like, so long as it responds to HTTP requests.
Nothing special here, but it does feel like a SPA. There a
!-->