The ingenious engine of web dev simplicity goes all-in with the Fetch API, native streaming, Idiomorph DOM merging, and more. Credit: Peter Griffin HTMX has been considered feature-complete for some time. It is a successful project that achieves its ambitious goals and is widely hailed, not to mention widely deployed in production. HTMX 2.0 was considered the final word. The creator promised there would be no HTMX 3.0. So of course, being developers, the HTMX team decided to rip out the engine and replace it with a new one based on JavaScript’s Fetch API. They named the new version HTMX 4.0 to keep the promise. Here is a fascinating tale of architecture and implementation that gives us a beautiful window into the inner machinations of the front-end industry. Simpler web development When asked for comment on the 3.0 leap frogging, HTMX Carson Gross gave me a one word quote: “Oops.” – Carson Gross, creator of HTMX Gross is one of my favorite industry personalities. It’s easy to see why. He created the Grug Brained Developer as well as HTMX. The former contains all the hard-bitten advice from a veteran coder that young grugs need to survive, delivered in the voice of a caveman. The latter is the physical manifestation of those ideas: a library that leverages HTML and REST to bring simplicity back to the web. The core of HTMX 4.0 is that the old transport protocol, the XHR object, is being removed and replaced with the modern (and universal) Fetch API. This is massive on two fronts. First, it was a massive amount of work for the HMTX team. Second, it’s a massive performance and DX win. Modern fetch() has a huge benefit in that it can stream responses. That means the front end can process and act on segments of the UI as they arrive, instead of waiting for the whole response to complete before taking action. This is similar to what React Server Components (RSC, a recent addition to React) do. There is a certain infatuation with new and clever techniques in software development. That is understandable, but it can become pathological at times. As a result, there has always been a countercurrent that urges us to look closely at the requirements and pare away the unnecessary until the simplest solution is found. HTMX is a banner carrier for that counterculture. In that spirit, the HTMX 2.0 line was declared the final version. It does what it was intended to, and is a complete and adequate solution. But then there is the truth that sometimes a better way to do things is found and more engineering work is merited. That is HTMX 4.0. Native streaming In HTMX 2.x we used the XHR object, XMLHttpRequest, which has its roots in the late 1990’s Internet Explorer. The browser had to buffer the entire response before it could swap. By adopting ReadableStream via the Fetch API, HTMX 4.0 can process and inject HTML fragments as they arrive. This achieves the holy grail of a streaming UI but does so with a tiny 14KB script. Moreover, we still are in the HTMX vernacular, meaning we can use any back end that can spit out a string. It’s a performance win that actually reduces your JavaScript footprint and makes the architecture simpler. In short, the use of Fetch is a refactor that should net both more power and less complexity. Idiomorph DOM merging Although native streaming is the most fundamental new aspect in HTMX 4.0, there is another really cool thing that the 4.0 refactor opens up. The idea of “morphing” or “diffing” HTML pages makes for superspeedy page changes with no additional complexity in many situations. It is perhaps best known from Hotwired. How it works: when a page (or fragment) arrives, an algorithm checks it against the existing content and replaces only the changes. HTMX 4.0 enables the default use of the Idiomorph algorithm, a fancy new approach to morphing one DOM tree into another. (The Idiomorph project is also led by Carson.) In HTMX 2.0, Idiomorph was an extension. In HTMX 4.0, you get it basically for free. Idiomorph, inspired by Hotwired’s Morphdom, evolved the idea of comparing two HTML docs and only updating the minimal set of data to the next level. Idiomorph has been adopted by Hotwired itself. There is a great technical description of the bottom-up, nested ID diffing algorithm that Idiomorph uses on its GitHub page. Idiomorph is not directly a benefit of the Fetch refactor, but is a benefit of the simplicity that Fetch has brought to the codebase. Using Fetch made it possible for the team to add Idiomorph to the core. Prop inheritance (a breaking change) HTMX 4.0 introduces a breaking change to prop inheritance. This change was not necessitated by the Fetch upgrade, but was based on real world experience. The team determined that it is safer and better DX to make HTMX props not inherit by default. In previous versions, attributes like hx-target inherited implicitly. This led to weird cases in which the children of an element were affected when it wasn’t clear why. In HTMX 4.0, inheritance is now explicit. You use the :inherited modifier to indicate which child elements should inherit, e.g., hx-target:inherited="#div". This respects the principle of locality of behavior (a Grug brained favorite). You no longer have to hunt through parent templates to find out where a button is supposed to swap its content. The history hack is history HTMX 2.x included a fancy history engine that tried to snapshot the local DOM and save it to localStorage. This was an optimization. It turned out to be brittle. HTMX 4.0 has abandoned this in favor of standard behavior, i.e., a page reload. Error handling and status-specific swapping Most InfoWorld readers will never have to face a 500 or a 404 error. But for those rare situations where a server returns an error code (yes, this is sarcasm), the new HTMX 4.0 behavior will be to swap in the content. Before, the request failed silently. This change will help developers provide immediate visual feedback to the user rather than leaving them with a broken or frozen screen. The really cool part of this update is the new status-specific swapping syntax. You can now define different behaviors for different HTTP codes directly in the HTML. By using syntax like hx-status:404="#not-found" or hx-status:5xx="#error-notice", you can elegantly route different server errors to distinct UI elements. The <hx-partial> tag The addition of <hx-partial> is a major structural improvement. It allows you to wrap fragments in a response so they can target specific elements explicitly (e.g., <hx-partial hx-target="#sidebar">). It’s a cleaner, more readable alternative to the old “out-of-band” (OOB) swaps. This is similar to Hotwired’s Turbo Streams. (So we see that HTMX and Hotwired are engaging in fruitful co-influence.) The idea is that we allow the server to send a collection of fragments tagged with targets, and these are placed in the UI. This allows for complex, multi-point updates to the interface based on a single server response. Native view transitions To top it all off, HTMX 4.0 now integrates with the browser’s native View Transitions API by default. This allows for app-like, animated transitions between page states—like fading or sliding—with zero extra CSS or JavaScript required. Sidestepping JavaScript complexity Even if you are unfamiliar with HTMX, it is worth looking at to understand what exactly it is trying to do. It is an important angle on web development. Along with friends like Hotwired, HTMX demonstrates the possibilities of taking the simplest standard features and wringing the most power from them possible. It’s impossible not to look at the whole landscape slightly differently once you get it. Even if you still use and appreciate reactive front ends (and I do). HTMX asks the question, what could we accomplish with Hypermedia if we were very clever? The answer is, we can accomplish quite a lot, and sidestep much JavaScript complexity in the process. Development ToolsEmerging TechnologyJavaScriptProgramming LanguagesSoftware DevelopmentWeb Development