A hard constraint on the project is that the unminified, uncompressed size must be less than that of the minified & compressed version of the (excellent) preact library (currently 4.6Kb).
I think it’s a good benchmark. When I see a library that’s a competitor to React and claims to be minimal, I compare them to Preact, in terms of bundle size, and they usually fail. To me, what’s the point of losing the declarative model and still not being as small as Preact?
fixi is in part designed to be plausibly run without either minification or compression, both of which require a fair amount of technical sophistication. Therefore I decided to use the minified & compressed version of Preact as an admittedly arbitrary benchmark for what “small enough” is.
at this point I’m very confident that the unminified & uncompressed version of fixi will be ~25% smaller than the minified & compressed version of preact, which I’m happy with. (This is not to denigrate the achievement preact, which is a great project and has a much more complicated task.)
I love how lean this is(the code is even quite readable!). As a far away admirer of htmx/hyperscript, I haven’t had the chance to use them for something yet, this has some neat stuff, particularly using fetch() and MutationObserver. Great design tradeoffs!
I’m not entirely sure why/when somebody should use htmx over fixi.js. Or what are the options if somebody wants something with a mixture of the features of htmx and fixi.js. Is the idea that if you need anything more than that fixi.jsoffers, one should turn tohtmx`?
I also wonder if this’ll start a trend of “build-less HTMX alternative frameworks”, which doesn’t need to be a bad thing, but it would be a bit ironic.
Fixi uses dom transition that is not well supported yet (FF doesn’t support it so smooth element transitions will appear as sudden switches, which you might or might not care about), and drops some legacy browsers support. Other than this is just stripped down version of HTMX, AFAICT.
htmx is much more fully featured, with things like history support, boosting, etc.
fixi almost certainly requires a user to write some JavaScript to make it work the way you want in a real world situation, so if you are comfortable with that then it’ll be great, but a lot of folks just want that code to be written for them, in which case htmx is a better choice
I also wonder if this’ll start a trend of “build-less HTMX alternative frameworks”, which doesn’t need to be a bad thing, but it would be a bit ironic.
I think this would be fantastic. I love htmx, but sometimes I wish there were more “competitors” in the space exploring different designs (and of course as seen here, taking advantage of potentially new browser APIs). For me personally, htmx is like 80% great, 20% a bit awkward, so I’d love to see more exploration in case maybe an alternative might suit me more. Nice to see alpine-ajax, data-star etc. And of course more people using these types of “juiced-up html libraries” will bring bug fixes, smooth edges, etc.
I was convinced about this for some use cases when I saw the hx-swap on the front page.
A number of years ago I had considered one of the biggest vulnerabilities in browsers was actually the support for javascript. How could you write applications without it? You replace them with declarative features that can do certain very specific things and leave most of the logic to the backend.
This kind of has the aroma of that sort of thing. I don’t have a lot of time to look into this further, but I would love to hear from others if this is in any way accurate.
the general concept you are describing is called “transclusion” in the hypermedia world and htmx generalizes it. HTML actually supports a form of transclusion via iframes and the target attribute on links and forms, but it is very limited.
If we can get triptych into the HTML spec (probably a decades-long effort) then you will be able to do quite a bit more with web pages without the need for scripting.
One of my favorite aspects of htmx is how it allows languages like Delphi be first class citizens in web development. We call this Hypermedia On Whatever you’d Like (HOWL):
The differences between these 2.0 release notes and those from a more common javascript ecosystem rube goldberg machine library could hardly be more stark.
Almost no breaking changes, an implicit backward compatibility goal, and an easy upgrade path with configuration settings reverting to 1.0 behavior. Even temporarily letting people continue to do bad things like using non-versioned CDN URLs is very user-friendly.
Did you have any particular libraries in mind? Presumably not React, which only had 3 major releases between 2016 and 2020, didn’t have many few breaking changes, and didn’t require much work to upgrade for most people. Version 17 in particular was focused at making it easier for people to upgrade by supporting older versions or React running alongside newer ones:
In particular, React 17 is a “stepping stone” release that makes it safer to embed a tree managed by one version of React inside a tree managed by a different version of React.
It also makes it easier to embed React into apps built with other technologies.
I wouldn’t advocate for stagnating libraries and never introducing breaking changes. So I’m not pointing to this list to say “aha! more breaking changes – bad”. It’s more to point out that next.js has such a large surface area, that it’s virtually impossible to advance the library’s development without those advancements having significant impact on an application’s dependencies and internals.
It’s also not about the quantity of breaking changes to me, but the severity. Next 13 bumped React from 17 to 18 and Node from 12 to 14. Combined, those two dependencies have massive reach. They were of course necessary changes, particularly with Node reaching EOL.
Obviously Next is a far more complex library than htmx, so it’s bound to have more breaking changes every release. I believe the crucial difference is that htmx is virtually immune to the sort of sweeping dependency changes to things like Node, Webpack, React, etc. when upgrading. And with such a small surface area, you’re more likely to be able to codemod your way to a new version, if a codemod is necessary at all. It’s never going to force you to update any of your build tooling because it has no build step. It’s never going to force you to upgrade React or some other frontend library, because it’s agnostic to what libraries are used on the frontend. Being small and focused is a virtue.
those from a more common javascript ecosystem rube goldberg machine library could hardly be more stark.
It’s a library that hacks in magic HTML attributes with >14KB (minified, zipped) of JS. That’s pretty “rube goldberg” to me even if it is a useful library.
It seems the only noteworthy change that marks this as a major version is the drop in support for IE11, so there’s not much to talk about.
I don’t think we’re likely to agree on much if we don’t agree that htmx’s approach to work with standards, rather than against them, is what’s most important about its approach. I don’t see adorning html elements with data-hx as a hack at all, but working within the standards.
You’re right in that there’s nothing splashy in this release. I prefer it that way, as I think this release was about providing a nicer backbone for future work and extension development. It gets htmx closer to “complete”, with future work happening in extensions.
There are some significant compatibility features. e.g. the 2.0 release uses FormData which improves compatibility with Web component libraries that provide form inputs.
This is very clever! I’ve been a htmx user for a good while but I’m not super happy with the implementation, so this minimalistic alternative which focuses on existing HTML features is very appealing to me. I look forward to trying it out in real projects.
It’s very large for what it does and the code is somewhat convoluted in a way I wouldn’t be happy maintaining. It has a number of features that seem to be competing with each other so it’s unclear in some cases which to use. When working with very large and complex pages we started to have performance problems with it that coming from the IE11 support code and animation code. We ended up forking htmx to remove them.
I would use it again for sure. I’m just not in love with it.
I did not open all the issues for my team, and there is absolutely no reason why I would spent my free time reading the htmx issue tracker for you. Do it yourself.
Esolangs that take the path of least resistance are so tired. An uninteresting, one-note joke with a docs page. Stack based, uses the most obvious elements as instructions, uses js for metaprogramming instead of using the structure of html itself to do interesting things.
Requiring valid HTML as programs would be way more interesting, and make it a fun polyglot language. It would be interesting as well if HTML programming language was able to generate HTML, or able to self-modify even, allowing you to programmatically create webpages with html syntax.
ikr, this looks like it was made as a joke by some idiot over the weekend as they tried to avoid folding laundry or something
some good news though!
HTML, the programming language does support self modification, in that you can call methods to modify the DOM of a program and then jump to the modified code via the <a> tag.
some additional good news as well: the language is entirely pluggable so you can redesign the entire thing by mutating the html.meta.commands object, making an HTML5 compatible language, redoing semantics, whatever you’d like!
and, in fact, HTML: the programming language, supports dynamic language modification in that, in HTML: the programming language, a program can actually modify the language itself during execution, since it can mutate html.meta.commands as well.
many possibilities, but the language is still terrible tho, probably designed by an idiot
certainly overlooked the self modification portion. <samp> does some of this I assume. Certainly can burn an insane amount of time making html.meta.commands accept valid html
you can access named objects via the <cite> command and then properties with the <rp> command.
here is an example of an HTML, the programming language, program that adds a new command to HTML, the programming language, and then executes that command:
we add a new command, <sup>, which does the exponent of the second-to-top element on the stack to the power on the top of the stack, and leave the result on the stack
the extension to HTML, the programming language is defined entirely within HTML, the programming language, itself
due to the way the interpreter of HTML, the programming language, works, you can also implement arbitrary control flow if you’d like, by returning the next element/command to execute (rather than “undefined”, which is used to tell the runtime to execute the next element, if any)
Lol, it depends how you wrote it. hx-trigger allows you to perform AJAX requests off of Javascript events, but I don’t know, I wouldn’t know how to correctly implement Datadog’s complex solution myself either.
Probably not with native htmx, because there seems to be some smart-ass stuff there to linearize back-end requests.
But: one of the reasons these dashboards need to be optimized is that they are in charge of both requesting data and creating DOM nodes based on received data. If your architecture is hypermedia-oriented, the client app is only in charge of requesting HTML widgets from the server, and the HTML itself is rendered by… the browser, which does that in a pretty optimized way.
So maybe we’re talking about one of the few use cases where htmx wouldn’t do the trick, but I’m not sure the hypermedia approach wouldn’t be relevant. And we’re talking about a non-trivial use case of a company that has a huge tech team.
As a long time SPA apologist and licensed reverend of the church of tiny backends, I find this genuinely difficult to follow. What is “hypermedia” even? A tree with some implied semantics? How is that different than any other data? Why should I be constructing it on the backend (that place that knows comparatively nothing about the client)?
The back button has been solved for over a decade.
The complexity of “the backend has to care what things look like” is also enormous.
Theres talk of longevity and churn, but I’m pretty sure if I wrote hx-target=... in 2012, I would not get the desired effect.
I haven’t managed state on a server beyond session cookies and auth in ages.
I saw a computer from 20 years ago use the internet just fine last weekend, and it needed some horrifying reverse proxy magic to make a secure connection, so “I’m using HTTPS” and “I’m supporting old hardware/OSs” is a contradiction anyway because decrypting HTTPS is more computationally intense than doom, and it’s also a moving target that we don’t get to pin. The end result is that if you can securely exchange information with a browser, it’s not ancient enough to need more than a few servings of polyfills to run a reasonably modern app.
React is the currently popular thing that makes stuff go vroom on the screen, so of course a lot of people make it more complicated than it needs to be, but like… remember early 2000s PHP CMSs? Those weren’t better, and if you did those wrong it was a security issue. At least a poorly written react UI can’t introduce a SQL injection.
To each their own, but I don’t get it 🤷♀️. I also don’t get how people end up with JS blobs bigger than a geocities rainbow divider gif, so maybe I’m just a loony.
Anything can be done wrong, and the fact that popular tools are used wrong often and obviously seems like a statistical inevitability, not a reason to try to popularize something different.
not a reason to try to popularize something different.
Why would you prevent people to popularize anything that actually solves some problems? Isn’t having choice a good thing? I’m this author of this talk about a React->htmx move, and I’m completely freaked out by how many people have seen my talk, as if it was a major relief for the industry. I am also amazed, when hiring young developers, by how most of them don’t even know that sending HTML from the server is possible. Javascript-first web UI tools have become so hegemonic that we need to remind people that they have been invented to tackle certain kind of issues, and come with costs and trade-offs that some (many? most?) projects don’t have to bear. And that another way is possible.
Anything can be done wrong, and the fact that popular tools are used wrong often and obviously seems like a statistical inevitability,
Probably the statistics are way higher for technologies that carry a lot of complexity. Like I said in my talk, it’s very easy for JS programmers to feel overwhelmed by the complexity of their stack. Many companies have to pay for a very experienced developer, or several of them. And it’s becoming an impossible economical equation.
The complexity of “the backend has to care what things look like” is also enormous.
With htmx or other similar technologies, “what things look like” is obviously managed in the browser: that’s where CSS and JS run. Server-side web frameworks are amazingly equipped for more than a decade now to generate HTML pages and fragments very easily and serve them at high speed to the browser without the need of a JS intermediary.
young developers … most of them don’t even know that sending HTML from the server is possible
I am shocked and stunned every single time I talk to someone who doesn’t know this. And if they are interested, I explain a little bit about how the web server can return any data, not just json.
Hypermedia encapsulates both current object state and valid operations on it in one partially machine-readable and partially user-readable structure.
A lobsters page, for example, lists the link and comments (the current state) and has a definition of how to comment: you can type in text and post it to the server. After you do that, the system replies with the updated state and possibly changed new valid operations. These are partially machine-readable - a generic program that understands HTML* can see it wants text to post to a particular server point - and partially user-readable, with layout and English text describing what it means and what it does.
Notice that this is all about information the backend applications knows: current data state and possible operations on it. It really has nothing to do with the client… which is part of why, when done well, it works on such a wide variety of clients.
hypermedia doesn’t have to be html either, but that’s the most common standard
HTMX is on my “things to try” list and I think its approach makes a lot of sense for many kinds of web apps. I love a lot of its design choices.
At the same time, I think the author neglects to mention some of the arguments against using it. The most obvious one: “Hey, can we make a mobile app too?” The React people will whip out React Native and reuse the server interaction code from the SPA. Their backend colleagues will barely have to do any work since it’s just another caller of the existing API. The server-rendered-HTML people, though, will scramble to design a native-app-friendly API from scratch and will be stuck maintaining two request-handling code paths to work with the same underlying data.
“We have several kinds of clients some of which aren’t web browsers” is a common enough scenario in my experience that I don’t think any HTML-centric approach is likely to be “the future” in the broad sense the post suggests. But it, or something like it, probably has a place in the future.
can we make a mobile app too? […] maintaining two request-handling code paths to work with the same underlying data.
Maybe is it the goal of Hotewire’s Strada? (upcoming in 2023)
“This makes it easy to progressively level-up web interactions with native replacements.”
The “HTMX for mobile” seems to be Hyperview: https://hyperview.org/ (from the hypermedia.systems book)
“Hyperview is a new hypermedia format and React Native client for developing server-driven mobile apps.”
(it says “server-driven” and “networked mobile apps” and warns: “If your app relies on offline data or local computations, Hyperview won’t be the right choice.”)
I do agree that HTMX is all-in on the web, and it’s not suitable for native mobile apps. I have made a decent PWA with it, though, and compared to comparable SPAs it runs like greased lightning in a mobile browser.
That said, for a lot of things, you really could take the same approach as the article does for serving HTMX fragments vs full pages — check for an Accept: application/json header, return the appropriate JSON representation after doing the same logic you would for HTMX or no-JS. The client would have to be from scratch, yeah, you don’t get the benefits of something like React Native, but the backend still barely has to change.
I’d be really interested to hear more about a PWA in HTMX. Is the service worker very app-specific (like knowing how to render data to HTML) or more generic (like caching visited pages)? Do you end up duplicating logic between the server and service worker, or did you find a good way to divide it up? Or did you try to share the logic somehow?
For my app, it was pretty much just caching and serving some static internal pages. Since the service worker has to be in JS, I didn’t want to make it too involved. My main goals were just to make the app installable on a phone home screen, and to do something sensible when offline.
It obviously depends on the app. HTMX is primarily targetting hypermedia not rich clients, so a mobile app is often not relevant. However, it would also not be a big deal to write a hypermedia client for mobile that was more limited/special case than a browser if you do need an app, and reuse the HTML descriptions etc without using a webview.
i am the creator of htmx & obviously glad to see it get some attention, but I also don’t want to overpromise what it can achieve. I think it makes a lot more possible in within the hypermedia paradigm of the web but, of course, there are times when it’s the right choice and times when it isn’t.
i have been working on a free book on hypermedia-based systems with a few other authors here:
I would say that in 99% (or more) of the existing http request DELETE and PUT are replaced by POST, and using something different is likely to break something, for little benefit
for exemple if you make two DELETE which should be idempotent and that your backend doesn’t treat them in a non idempotent way, your app is suddenly having a bug which can be hard to reproduce.
Not sure I get your point. If your backend is treating deletes as not idempotent you’re already wrong. And deletes in particular seem like a quite easy to make idempotent, just check if it has been deleted already before deleting.
What does it mean to delete something? Should I use DELETE if it’s a soft delete? What if can be undone for three hours? What if it deletes one thing but adds an audit record somewhere else?
DELETE adds nothing. The point is “can an intermediary cache this?” If yes then use GET. If not, POST.
URL paths are function names. The arguments to a GET function are query parameters. The arguments to POST functions are a JSON body (or form fields if you’re doing AJAX). You make up requests and responses that fit the domain instead of assuming everything is a resource with the same verbs. I’m also against putting resource IDs into URLs for APIs (you can do it for stuff end users see to make the URLs pretty, but not for APIs).
You make up requests and responses that fit the domain instead of assuming everything is a resource with the same verbs.
Aren’t you just stating that you prefer RPC, without actually engaging with the argument for hypermedia?
The argument is that “Uniform Interface Constraint” (resources with a standard set of methods) allows you to make general clients that can interact with your resources with no out of band information (like API docs), a la web browsers + html.
Admittedly, what you describe is, in fact, how the majority of most APIs today work, and there is an interesting discussion about why that is if hypermedia supposedly has so many advantages.
I think your argument would be more interesting if you stated why you think that goal doesn’t have value, especially given that the web itself works that way, that it solves problems like API versioning, and so forth.
I’m also against putting resource IDs into URLs for APIs
Why do you not like this specifically, out of curiosity? What do you prefer?
Second question first, resource IDs belong in query parameters. HTTP has many overlapping ways of sending data from client to server and server to client. The client can send information as a method verb, a URL path, a query parameter, a header, or a request body. There has to be some system to organize the arbitrary choices. The system is:
Verb is for read vs write.
URL path is the function to call.
Query parameters are the arguments to reads. Bodies are the arguments to writes.
Header is for authentication.
IDs are prettier in the URL path, but for an API, that doesn’t matter. You just need a convention that is easy to follow.
As for Hypermedia, I just care that the website is good for users and developers. Whatever the theory is behind it isn’t very important. It’s great that web browsers are universal tools, but that’s true for JSON APIs too, so “hypermedia-ness” only matters if it makes development easier or harder. I think probably HTMX is easier for most web apps, so that’s why I like it. Even then, I’m more partial to Alpine.JS because I feel like the core motivation for a lot of the HTMX partisans is just wanting to avoid learning JS.
I feel like the core motivation for a lot of the HTMX partisans is just wanting to avoid learning JS.
I know this is a selling point, but fwiw I have a lot of JS experience, consider myself good with it, have used React and other similar frameworks, but still like the simplicity of the old MPA model – htmx being for me just an upgrade. Having just the single data model of the resources on the server to think about it.
The system is:….
Agree with your point about “overlapping ways of sending data from client to server,” and also agree that having any clear system is more important than “the best system,” if there is one. I guess I’m not seeing why the classic system of “url path to describe resource”, “http verb to describe action” is not good enough… It can be stilted and noun-y, yes, but imo that’s not enough reason to throw away a perfectly good existing “system,” as it were.
I don’t like the classic “everything is a noun” system because it ends up needing a lot of requests to get anything done, and requests are the slowest thing you can do with a computer.
I’m working with the MailChimp V3 API this week, and to send a campaign takes three requests: 1. Create campaign 2. Set content 3. Send. In MailChimp API V2, it’s a single request, but they’re finally shutting it down at the end of the month, so I’m being forced to make the change. Because it’s three requests instead of one, I probably need to put it into a queue now because it won’t be reliably fast enough to get done in one request for my users, so now I have to deal with all the complications of asynchrony, and for what? The old API was better.
Seems like a reasonable complaint but orthogonal to the naming/noun-ness of the system. They could continue to support the version you prefer with something like POST “api.mailchimp.com/one-shot-emails” or “outbox” or whatever. That is, from a pure naming persepective, you can always transform back and forth between the two systems.
To your point, classic REST typically has aggregate endpoints return a list of ids, and then you have to make requests (possibly parallel) to each id resource to get the details, which is cumbersome. But nothing forces you to follow that if it doesn’t suit your use-case.
I call this “BrowserTP” since it’s a squished down version of HTTP based on what browsers supported in the early 00’s.
I would say thusly: HTTP is an RPC protocol where the method name (or function or procedure name if you wish) is the method (sometimes called the verb). The URL path is the object that you are calling the method on. The arguments are query string + body as you say.
And sure I can say “please create a deletion for the element in this collection with id 1” it’s not wrong per se, but why wouldn’t I just say “please delete element 1”
I agree that they aren’t really useful, but it takes very little effort for the author to add them and a lot of people want them.
Aside from the obviously minor difference of sending POST /thing/delete vs DELETE /thing, other HTTP verbs can introduce additional overhead with CORS:
Additionally, for HTTP request methods that can cause side-effects on server data (in particular, HTTP methods other than GET, or POST with certain MIME types), the specification mandates that browsers “preflight” the request, soliciting supported methods from the server with the HTTP OPTIONS request method […]
I was going to argue the opposite with approximately the very same line quoted.
If you and your webapp rely on the browser for some of the protection against some level of cross-site request forgery attacks, you can use the verbs as they were intended and rely on the browser to enforce them to be usable according to CORS rules.
i want to say that it add complexity: if you have a reverse proxy, it has to support the new verbs, if you have logs it should be aware of this verbs, if you have something in your infrastructure which used to ignore DELETE, and suddenly support it, it suddenly delete unwanted things
the book was originally set to be published by a big tech publisher, but they backed out so we are releasing the book for free on the web and we are going to try to self-publish it
we are in the process of re-writing the book with a bit more of a conceptual bend than what the publisher wanted, and we are happy with how it is turning out. It is a work in progress, and there are incomplete sections and some repetitive areas, but the structure is about where we want it and much of the content is finished
the book covers hypermedia in general, then htmx for hypermedia-driven web applications, then Hyperview for hypermedia-driven mobile applications
This explanation of the usefulness of hx-boost is something that had never occurred to me, and I’ve been thinking about (in addition to actually incrementally using it in new things) how HTMX improves my apps’ experience off and on for a few months now:
You might reasonably ask: what’s the advantage here? We are issuing an AJAX request and simply replacing the entire body.
Is that significantly different from just issuing a normal link request?
Yes, it is in fact different: with a boosted link, the browser is able to avoid any processing associated with the head tag. The head tag often contains many scripts and CSS file references. In the boosted scenario, it is not necessary to re-process those resources: the scripts and styles have already been processed and will continue to apply to the new content. This can often be a very easy way to speed up your hypermedia application.
That’s a good point, and might merit mention in the official documentation, because my initial reaction to hx-boost was to ignore it because there didn’t seem to be much joy in using AJAX just to transfer the full page anyway. I was mostly thinking in terms of network transfer. I don’t think I’m alone.
There’s a reason this sort of thing isn’t mainstream (anymore). “Async transparent” is a synonym for “free-threaded”. If you’re going to have mutable state you need some indicators of where discontinuities in state can happen (i.e., modified by non local code) to make reasoning about your code possible. The other way you can go is the Erlang design where suspending the local stack for IO doesn’t affect reasoning because there’s no local mutable state.
yes, I don’t think async-transparency is a good fit for general purpose programming, but it is nice for front end scripting, and given the already-single-threaded nature of JavaScript, it works pretty well and opens up some nice patterns with respect to event-driven programming that are painful in JavaScript.
a cool example is what we call “The Akşimşek Gambit”, a bit of code that Deniz Akşimşek wrote to make a div draggable:
repeat until event pointerup from document
wait for pointermove(pageX, pageY) or
pointerup(pageX, pageY) from document
add { left: ${pageX - xoff}px; top: ${pageY - yoff}px; }
end
where you loop until a pointer up from the document occurs, and then wait in the loop for either a move or pointer up.
Insane, but it works, and it’s pretty darned cool.
Which, come to think of it, is a pretty reasonable description of hyperscript…
It might be less code for this one application. But I feel like everyone agreed that Angular-style directives have a very low ceiling, and eventually you just want the power of a programming language to generate your actual markup. This way you’re not stuck wading through tons of documentation to figure out the arcane attribute syntax for some hyper-specific use case.
You have to find the specific attribute that you need (hx-trigger) and then you have to work with the inner scheduling DSL for when to poll (every 2 seconds). What if I want to poll every odd hour? What if I want to poll only on Mondays?
I’m sure there’s a place where this is useful, maybe for small applications or side projects. It probably is slightly quicker initially. But I’m not alone in abandoning this style of UI development a long time ago.
For more dynamic polling, I would write a small script to trigger an event, and then listen for that event.
The crux of htmx is hypermedia: exchanging hypermedia with a server and using hypertext as the engine of application state. It will work well for some types of applications, and size is less important than the flavor of the application: gmail would be great as a hypermedia application, google sheets would not. The core question is: can the UX I desire be achieved with hypermedia and my hope is that, with htmx, the answer to that question is “yes” for a larger subset of applications.
I definitely agree that there are appropriate hypermedia applications - for me, it’s static content like blogs. I always classified gmail as the exact kind of application that is not good for hypermedia. In fact, Gmail is the complete poster child for AJAX and SPAs. It’s always referenced as one of the first applications that used the SPA style, and I think that makes total sense.
I think you could build a very nice email client entirely in htmx, using hypermedia clients. I like to mention GMail because it was done as a SPA and, in my opinion, didn’t need to be. Certainly what react was created for, to append a comment to a comment list, didn’t require an SPA. Something like Sheets or Maps, on the other hand, would be hard to implement using the hypermedia network architecture.
In general my hope is to expand the class of applications, dynamism & the general UX level that people feel they can achieve with hypermedia:
This is the exact kind of considerations I’m trying to address with my talk. In the demo part I show a faceted search engine, with a special facet option that updates its results according to a change on server state which is the consequence of a user action elsewhere on the page. Pretty far from “static content”, “small application” or “side project”, don’t you think? It’s the same level of complexity that what you can find on Gmail UI.
Yeah, I tend to prefer Alpine.js because even though it is inspired by Angular/Vue, at the end of the day, it’s just JavaScript. If you wanted to make a polling directive in Alpine, you would just write the normal window.setInterval code for it, instead of going into some “inner platform” language.
As they say in the talk, when they were beginning they were told they had to use react for their application to be “modern”. Sadly, many people think that that’s true, and don’t realize that there are hypermedia-oriented options like htmx, unpoly and hotwire that can give you more interactivity within the hypermedia model. So they end up going react, because everyone else is, and that’s what HR hires for.
I’m not the speaker, I’m the creator of htmx, so not an unbiased source. :)
David mentions unpoloy and hotwire, two other excellent hypermedia oriented options in his talk, and he uses Stimulus for some javascript (rather than my own hobby horse, https://hyperscript.org) but he didn’t say why he picked htmx.
Generally, I would say:
htmx is lowest level, very focused on extending HTML
unpoly is more batteries-included and supports progressive enhancement better
hotwire is the most automagical of the bunch, and very polished (+ mobile support)
We chose htmx because of its simplicity (data-attribute driven, very few but very generic features). We evaluated:
hotwired, which would have been a great option since it works particularly well with Stimulus that we were already using on another project. It seemed just a bit too much complicated because it introduces new markup tags, and it has a strong emphasis on real-time stuff that we did not need.
unpoly, which was pretty similar to htmx at first sight. But it seemed to us that the community was less active, so we didn’t push the evaluation further
Hi there, author of the talk here, sorry for the delay.
Our application is not an article aggregator, it’s much more complex than that: it presents future laws being discussed in French parliament. The right part is the text that is being discussed, and on the left you have the amendments filed by parliamentarians, and which aim to change the text.
But still, you’re right: “Why would you have used react for a site like this in the first place?” is precisely the question I asked when I discovered the modern tools of the hypermedia approach. But not because our application is simple: because the hypermedia approach can achieve a lot more than what most people think. It’s not just for “article aggregators”, “student projects”, “quick prototyping”, “small personal websites” and simple CRUDs. All day long I use professional tools that would benefit the hypermedia approach: Gmail, Sentry, AWS console, and others…
And this is what my talk is about: breaking the FUD spread by some people about what is doable with “old-school” web apps (web pages) and what is not doable with that approach, thus requiring the whole API+SPA stack.
Perhaps a more important change is that the entire team became “full-stack” developers, instead of having a hard front-end/back-end split. That’s huge, in my opinion
One challenge I’ve found in that front is that if you want good frontend developers it’s very hard to find those that are also willing to deal with backend development, or having much of any skill there. There are many good backend developers that are alright at dealing with frontend, but above a certain quality bar it’s basically impossible.
I do think it’s great to be able to have people who can really handle the entire stack, but there are issues with mandating fullstack-ness, so you gotta be a bit careful there. This is “solvable” by pairing people up but then you get into another can of worms based on who you have on the team.
Is that split really front-end vs back-end or infrastructure vs UI? I’ve not done serious web development, but my guess would be that it’s hard to find good interaction specialists but much easier to find people who can write code that runs on either end of a network connection. Are there teams where ‘UI designer’ is a separate role but the engineers work on the whole of the application stack?
Are there teams where ‘UI designer’ is a separate role but the engineers work on the whole of the application stack?
So I’ve worked on a team that ended up almost there. There was one “pure” UI designer, and another who was UI design but liked coding. There were a lot of growing pains because he couldn’t properly prototype stuff due to our backend being hard to run for people not used to the terminal.
They both could get work done provided the right tools! But the tooling we had was made (essentially) for backend engineers, so it was a huge amount of friction. That and there was just a different kind of workflow.
But yeah, the overall lesson was that there were people able to do the work we really were missing from the team (remember, the other engineers could write code in both domains! Just the frontend code wasn’t great), but those people could not really work on the team without us adjusting expectations about infra-related demands
Yes, but we have strong evidence from the old days, pre-SPA frameworks, that server-rendered templates are manageable for developers who also do back end work.
It was only when SPAs and their attendant complexity came along that the split between front-end and back-end became pronounced.
I haven’t observed that at all. Real frontend specialty, like advanced CSS and UX stuff, has always been taken care of by frontend specialists. Everything in between, pretty much anyone can do.
The evidence being that full stack development was a relatively common thing pre-SPA era.
Not saying that there won’t always be designers involved, especially once you start talking about externally facing applications. But htmx puts full stack back on the table as a potential option in a way that SPA libraries and their attendant complexity do not.
Build time might be a bit of a red herring, as I bet it was webpack. esbuild is absolutely blazing fast and gets rid of that whole axis.
I do think that measuring what happens in practice rather than theoretical minimums is good, and like up until recently webpack was unfortunately “the thing”, but at least on that front there are ways to make improvements without having to manipulate the universe
Is there a reason for this?
I think it’s a good benchmark. When I see a library that’s a competitor to React and claims to be minimal, I compare them to Preact, in terms of bundle size, and they usually fail. To me, what’s the point of losing the declarative model and still not being as small as Preact?
I think its a good benchmark for minified/compressed code. Not so good of a benchmark for assessing unminified code however.
By size, Fixi is trying to fit into the equivalent of a single fully documented function of Preact’s, in terms of line count.
fixi is in part designed to be plausibly run without either minification or compression, both of which require a fair amount of technical sophistication. Therefore I decided to use the minified & compressed version of Preact as an admittedly arbitrary benchmark for what “small enough” is.
at this point I’m very confident that the unminified & uncompressed version of fixi will be ~25% smaller than the minified & compressed version of preact, which I’m happy with. (This is not to denigrate the achievement preact, which is a great project and has a much more complicated task.)
I love how lean this is(the code is even quite readable!). As a far away admirer of htmx/hyperscript, I haven’t had the chance to use them for something yet, this has some neat stuff, particularly using
fetch()andMutationObserver. Great design tradeoffs!I’m not entirely sure why/when somebody should use
htmxoverfixi.js. Or what are the options if somebody wants something with a mixture of the features ofhtmxand fixi.js. Is the idea that if you need anything more than thatfixi.jsoffers, one should turn tohtmx`?I also wonder if this’ll start a trend of “build-less HTMX alternative frameworks”, which doesn’t need to be a bad thing, but it would be a bit ironic.
Fixi uses dom transition that is not well supported yet (FF doesn’t support it so smooth element transitions will appear as sudden switches, which you might or might not care about), and drops some legacy browsers support. Other than this is just stripped down version of HTMX, AFAICT.
Graceful degradation is a great feature of HTML
htmx is much more fully featured, with things like history support, boosting, etc.
fixi almost certainly requires a user to write some JavaScript to make it work the way you want in a real world situation, so if you are comfortable with that then it’ll be great, but a lot of folks just want that code to be written for them, in which case htmx is a better choice
I think this would be fantastic. I love htmx, but sometimes I wish there were more “competitors” in the space exploring different designs (and of course as seen here, taking advantage of potentially new browser APIs). For me personally, htmx is like 80% great, 20% a bit awkward, so I’d love to see more exploration in case maybe an alternative might suit me more. Nice to see alpine-ajax, data-star etc. And of course more people using these types of “juiced-up html libraries” will bring bug fixes, smooth edges, etc.
Of course maybe Fixi is what I’m looking for!
I was convinced about this for some use cases when I saw the hx-swap on the front page.
A number of years ago I had considered one of the biggest vulnerabilities in browsers was actually the support for javascript. How could you write applications without it? You replace them with declarative features that can do certain very specific things and leave most of the logic to the backend.
This kind of has the aroma of that sort of thing. I don’t have a lot of time to look into this further, but I would love to hear from others if this is in any way accurate.
alex petros, on the htmx team, is working to get some of the ideas of htmx integrated into the HTML spec proper:
https://alexanderpetros.com/triptych/
the general concept you are describing is called “transclusion” in the hypermedia world and htmx generalizes it. HTML actually supports a form of transclusion via iframes and the
targetattribute on links and forms, but it is very limited.If we can get triptych into the HTML spec (probably a decades-long effort) then you will be able to do quite a bit more with web pages without the need for scripting.
like an idiot, arguing w/people on HN:
https://news.ycombinator.com/item?id=42413845
gonna ski tomorrow
One of my favorite aspects of htmx is how it allows languages like Delphi be first class citizens in web development. We call this Hypermedia On Whatever you’d Like (HOWL):
https://htmx.org/essays/hypermedia-on-whatever-youd-like/
I made a meme about it: https://htmx.org/img/memes/20yearold.png
I have to strongly resist the urge to buy the updated physical copy… sigh
I’m very sad they appear to have replaced the wonderful cover by Niel Panchal / Berkeley Graphics
Original cover is still available on the hard cover:
https://www.amazon.com/Hypermedia-Systems-Carson-Gross/dp/B0C9S88QV6/ref=sr_1_1
And also in poster form:
https://swag.htmx.org/products/hypermedia-systems-cover-poster
We sell the 12x18 at cost so anyone who wants the cover can have it as cheaply as possible.
For the paperback we wanted to do something different and I’m very happy with how the cover turned out.
I loved the old cover. But “418 Teahouse & Cafe” makes me want the new one on a poster.
Yeah, the new cover is cool! Will that one be available in poster form at some point?
definitely plan on offering it as a poster
The differences between these
2.0release notes and those from a more common javascript ecosystem rube goldberg machine library could hardly be more stark.Almost no breaking changes, an implicit backward compatibility goal, and an easy upgrade path with configuration settings reverting to
1.0behavior. Even temporarily letting people continue to do bad things like using non-versioned CDN URLs is very user-friendly.Did you have any particular libraries in mind? Presumably not React, which only had 3 major releases between 2016 and 2020, didn’t have many few breaking changes, and didn’t require much work to upgrade for most people. Version 17 in particular was focused at making it easier for people to upgrade by supporting older versions or React running alongside newer ones:
I believe next.js falls into that category, e.g. https://nextjs.org/blog/next-13#breaking-changes
I wouldn’t advocate for stagnating libraries and never introducing breaking changes. So I’m not pointing to this list to say “aha! more breaking changes – bad”. It’s more to point out that next.js has such a large surface area, that it’s virtually impossible to advance the library’s development without those advancements having significant impact on an application’s dependencies and internals.
It’s also not about the quantity of breaking changes to me, but the severity. Next 13 bumped React from 17 to 18 and Node from 12 to 14. Combined, those two dependencies have massive reach. They were of course necessary changes, particularly with Node reaching EOL.
Obviously Next is a far more complex library than htmx, so it’s bound to have more breaking changes every release. I believe the crucial difference is that htmx is virtually immune to the sort of sweeping dependency changes to things like Node, Webpack, React, etc. when upgrading. And with such a small surface area, you’re more likely to be able to codemod your way to a new version, if a codemod is necessary at all. It’s never going to force you to update any of your build tooling because it has no build step. It’s never going to force you to upgrade React or some other frontend library, because it’s agnostic to what libraries are used on the frontend. Being small and focused is a virtue.
It’s a library that hacks in magic HTML attributes with >14KB (minified, zipped) of JS. That’s pretty “rube goldberg” to me even if it is a useful library.
It seems the only noteworthy change that marks this as a major version is the drop in support for IE11, so there’s not much to talk about.
I don’t think we’re likely to agree on much if we don’t agree that htmx’s approach to work with standards, rather than against them, is what’s most important about its approach. I don’t see adorning html elements with
data-hxas a hack at all, but working within the standards.You’re right in that there’s nothing splashy in this release. I prefer it that way, as I think this release was about providing a nicer backbone for future work and extension development. It gets htmx closer to “complete”, with future work happening in extensions.
There are some significant compatibility features. e.g. the 2.0 release uses
FormDatawhich improves compatibility with Web component libraries that provide form inputs.unfair! the website now supports dark mode!
This is very clever! I’ve been a htmx user for a good while but I’m not super happy with the implementation, so this minimalistic alternative which focuses on existing HTML features is very appealing to me. I look forward to trying it out in real projects.
What issues did you find with the implementation?
It’s very large for what it does and the code is somewhat convoluted in a way I wouldn’t be happy maintaining. It has a number of features that seem to be competing with each other so it’s unclear in some cases which to use. When working with very large and complex pages we started to have performance problems with it that coming from the IE11 support code and animation code. We ended up forking htmx to remove them.
I would use it again for sure. I’m just not in love with it.
can I get a link to your fork? i’d like to see what was giving you trouble.
I’ve left the company now, but we shared some of the problems on the htmx issue tracker
can you link them here?
You’re asking me to search through the htmx issue tracker for performance related tickets for you?
i looked at perf and performance and it didn’t turn up much I could see (I’m old though)
https://github.com/bigskysoftware/htmx/issues?q=is%3Aissue+is%3Aopen+perf https://github.com/bigskysoftware/htmx/issues?q=is%3Aissue+is%3Aopen+performance
I looked here but didn’t see anything:
https://github.com/bigskysoftware/htmx/issues/created_by/lpil
You don’t need to tell me your github username, just plug it in there and send along the issues and I’ll take a look
I did not open all the issues for my team, and there is absolutely no reason why I would spent my free time reading the htmx issue tracker for you. Do it yourself.
Just fyi htmx 2 removes IE support. They are testing alpha releases right now.
Esolangs that take the path of least resistance are so tired. An uninteresting, one-note joke with a docs page. Stack based, uses the most obvious elements as instructions, uses js for metaprogramming instead of using the structure of html itself to do interesting things.
Requiring valid HTML as programs would be way more interesting, and make it a fun polyglot language. It would be interesting as well if HTML programming language was able to generate HTML, or able to self-modify even, allowing you to programmatically create webpages with html syntax.
So like xslt?
ikr, this looks like it was made as a joke by some idiot over the weekend as they tried to avoid folding laundry or something
some good news though!
HTML, the programming language does support self modification, in that you can call methods to modify the DOM of a program and then jump to the modified code via the <a> tag.
some additional good news as well: the language is entirely pluggable so you can redesign the entire thing by mutating the
html.meta.commandsobject, making an HTML5 compatible language, redoing semantics, whatever you’d like!and, in fact, HTML: the programming language, supports dynamic language modification in that, in HTML: the programming language, a program can actually modify the language itself during execution, since it can mutate
html.meta.commandsas well.many possibilities, but the language is still terrible tho, probably designed by an idiot
certainly overlooked the self modification portion.
<samp>does some of this I assume. Certainly can burn an insane amount of time makinghtml.meta.commandsaccept valid htmlby “entirely pluggable” what do you mean? can i modify html.meta.commands from within HTML? I don’t need any way to access named objects.
you can access named objects via the <cite> command and then properties with the <rp> command.
here is an example of an HTML, the programming language, program that adds a new command to HTML, the programming language, and then executes that command:
https://codepen.io/1cg/pen/KKJbQxq?editors=1001
we add a new command, <sup>, which does the exponent of the second-to-top element on the stack to the power on the top of the stack, and leave the result on the stack
the extension to HTML, the programming language is defined entirely within HTML, the programming language, itself
due to the way the interpreter of HTML, the programming language, works, you can also implement arbitrary control flow if you’d like, by returning the next element/command to execute (rather than “undefined”, which is used to tell the runtime to execute the next element, if any)
The mechanism for collectively deciding if something is interesting or not is already in place, and that is the voting system.
I agree that they could have made even more out of the idea, though.
How would you build something like this with htmx?
(A request scheduler for pages that make dozens or hundreds of network requests)
You probably wouldn’t write the request scheduler with HTMX, you’d just write it in Javascript.
And then how would you hook it into an application built with HTMX?
You would probably build it as an island of interactivity and then integrate it w/ the broader htmx application via events:
https://htmx.org/essays/when-to-use-hypermedia/#if-your-ui-state-is-updated-extremely-frequently
https://htmx.org/essays/hypermedia-friendly-scripting/
Lol, it depends how you wrote it.
hx-triggerallows you to perform AJAX requests off of Javascript events, but I don’t know, I wouldn’t know how to correctly implement Datadog’s complex solution myself either.Probably not with native htmx, because there seems to be some smart-ass stuff there to linearize back-end requests.
But: one of the reasons these dashboards need to be optimized is that they are in charge of both requesting data and creating DOM nodes based on received data. If your architecture is hypermedia-oriented, the client app is only in charge of requesting HTML widgets from the server, and the HTML itself is rendered by… the browser, which does that in a pretty optimized way.
So maybe we’re talking about one of the few use cases where htmx wouldn’t do the trick, but I’m not sure the hypermedia approach wouldn’t be relevant. And we’re talking about a non-trivial use case of a company that has a huge tech team.
As a long time SPA apologist and licensed reverend of the church of tiny backends, I find this genuinely difficult to follow. What is “hypermedia” even? A tree with some implied semantics? How is that different than any other data? Why should I be constructing it on the backend (that place that knows comparatively nothing about the client)?
The back button has been solved for over a decade.
The complexity of “the backend has to care what things look like” is also enormous.
Theres talk of longevity and churn, but I’m pretty sure if I wrote
hx-target=...in 2012, I would not get the desired effect.I haven’t managed state on a server beyond session cookies and auth in ages.
I saw a computer from 20 years ago use the internet just fine last weekend, and it needed some horrifying reverse proxy magic to make a secure connection, so “I’m using HTTPS” and “I’m supporting old hardware/OSs” is a contradiction anyway because decrypting HTTPS is more computationally intense than doom, and it’s also a moving target that we don’t get to pin. The end result is that if you can securely exchange information with a browser, it’s not ancient enough to need more than a few servings of polyfills to run a reasonably modern app.
React is the currently popular thing that makes stuff go vroom on the screen, so of course a lot of people make it more complicated than it needs to be, but like… remember early 2000s PHP CMSs? Those weren’t better, and if you did those wrong it was a security issue. At least a poorly written react UI can’t introduce a SQL injection.
To each their own, but I don’t get it 🤷♀️. I also don’t get how people end up with JS blobs bigger than a geocities rainbow divider gif, so maybe I’m just a loony.
Anything can be done wrong, and the fact that popular tools are used wrong often and obviously seems like a statistical inevitability, not a reason to try to popularize something different.
You must be using a different web than me.
Why would you prevent people to popularize anything that actually solves some problems? Isn’t having choice a good thing? I’m this author of this talk about a React->htmx move, and I’m completely freaked out by how many people have seen my talk, as if it was a major relief for the industry. I am also amazed, when hiring young developers, by how most of them don’t even know that sending HTML from the server is possible. Javascript-first web UI tools have become so hegemonic that we need to remind people that they have been invented to tackle certain kind of issues, and come with costs and trade-offs that some (many? most?) projects don’t have to bear. And that another way is possible.
Probably the statistics are way higher for technologies that carry a lot of complexity. Like I said in my talk, it’s very easy for JS programmers to feel overwhelmed by the complexity of their stack. Many companies have to pay for a very experienced developer, or several of them. And it’s becoming an impossible economical equation.
With htmx or other similar technologies, “what things look like” is obviously managed in the browser: that’s where CSS and JS run. Server-side web frameworks are amazingly equipped for more than a decade now to generate HTML pages and fragments very easily and serve them at high speed to the browser without the need of a JS intermediary.
I am shocked and stunned every single time I talk to someone who doesn’t know this. And if they are interested, I explain a little bit about how the web server can return any data, not just json.
Hypermedia encapsulates both current object state and valid operations on it in one partially machine-readable and partially user-readable structure.
A lobsters page, for example, lists the link and comments (the current state) and has a definition of how to comment: you can type in text and post it to the server. After you do that, the system replies with the updated state and possibly changed new valid operations. These are partially machine-readable - a generic program that understands HTML* can see it wants text to post to a particular server point - and partially user-readable, with layout and English text describing what it means and what it does.
Notice that this is all about information the backend applications knows: current data state and possible operations on it. It really has nothing to do with the client… which is part of why, when done well, it works on such a wide variety of clients.
To be fair, “the client” is a web page 9 out of 10 times so why abstract it away.
here you go:
https://hypermedia.systems
TLDR: hypermedia is a media, say, a text, with hypermedia controls in it. A lot more detail to be found in the book, or on the essays page:
https://htmx.org/essays
HTMX is on my “things to try” list and I think its approach makes a lot of sense for many kinds of web apps. I love a lot of its design choices.
At the same time, I think the author neglects to mention some of the arguments against using it. The most obvious one: “Hey, can we make a mobile app too?” The React people will whip out React Native and reuse the server interaction code from the SPA. Their backend colleagues will barely have to do any work since it’s just another caller of the existing API. The server-rendered-HTML people, though, will scramble to design a native-app-friendly API from scratch and will be stuck maintaining two request-handling code paths to work with the same underlying data.
“We have several kinds of clients some of which aren’t web browsers” is a common enough scenario in my experience that I don’t think any HTML-centric approach is likely to be “the future” in the broad sense the post suggests. But it, or something like it, probably has a place in the future.
Maybe is it the goal of Hotewire’s Strada? (upcoming in 2023)
“This makes it easy to progressively level-up web interactions with native replacements.”
The “HTMX for mobile” seems to be Hyperview: https://hyperview.org/ (from the hypermedia.systems book)
“Hyperview is a new hypermedia format and React Native client for developing server-driven mobile apps.”
(it says “server-driven” and “networked mobile apps” and warns: “If your app relies on offline data or local computations, Hyperview won’t be the right choice.”)
I do agree that HTMX is all-in on the web, and it’s not suitable for native mobile apps. I have made a decent PWA with it, though, and compared to comparable SPAs it runs like greased lightning in a mobile browser.
That said, for a lot of things, you really could take the same approach as the article does for serving HTMX fragments vs full pages — check for an Accept: application/json header, return the appropriate JSON representation after doing the same logic you would for HTMX or no-JS. The client would have to be from scratch, yeah, you don’t get the benefits of something like React Native, but the backend still barely has to change.
I’d be really interested to hear more about a PWA in HTMX. Is the service worker very app-specific (like knowing how to render data to HTML) or more generic (like caching visited pages)? Do you end up duplicating logic between the server and service worker, or did you find a good way to divide it up? Or did you try to share the logic somehow?
For my app, it was pretty much just caching and serving some static internal pages. Since the service worker has to be in JS, I didn’t want to make it too involved. My main goals were just to make the app installable on a phone home screen, and to do something sensible when offline.
Do you consider media queries a insufficient approach to responsibility?
The author commented in this thread, literally three hours before you did, and linked to an essay he wrote about when not to use htmx.
That is the author of htmx, not the OP.
Haha, good point.
https://htmx.org/essays/when-to-use-hypermedia/
https://htmx.org/essays/splitting-your-apis/
It obviously depends on the app. HTMX is primarily targetting hypermedia not rich clients, so a mobile app is often not relevant. However, it would also not be a big deal to write a hypermedia client for mobile that was more limited/special case than a browser if you do need an app, and reuse the HTML descriptions etc without using a webview.
* for some stuff[1]
i am the creator of htmx & obviously glad to see it get some attention, but I also don’t want to overpromise what it can achieve. I think it makes a lot more possible in within the hypermedia paradigm of the web but, of course, there are times when it’s the right choice and times when it isn’t.
i have been working on a free book on hypermedia-based systems with a few other authors here:
https://hypermedia.systems
[1] - https://htmx.org/essays/when-to-use-hypermedia/
I don’t get why htmx allow other http verb than GET and POST. from my point of view it add a layer of complexity without real benefit.
Are you saying DELETE and PUT should be replaced by POST? The idempotence property of these operations would be lost if you did that.
Yes. Other verbs are a waste of effort. They don’t benefit anything and it adds another design decision you don’t need to make.
I would say that in 99% (or more) of the existing http request DELETE and PUT are replaced by POST, and using something different is likely to break something, for little benefit
for exemple if you make two DELETE which should be idempotent and that your backend doesn’t treat them in a non idempotent way, your app is suddenly having a bug which can be hard to reproduce.
Not sure I get your point. If your backend is treating deletes as not idempotent you’re already wrong. And deletes in particular seem like a quite easy to make idempotent, just check if it has been deleted already before deleting.
Being limited to get and post was the biggest mistake forms ever made and held the web back for years with shitty hacks like ?_method=DELETE
What does it mean to delete something? Should I use DELETE if it’s a soft delete? What if can be undone for three hours? What if it deletes one thing but adds an audit record somewhere else?
DELETE adds nothing. The point is “can an intermediary cache this?” If yes then use GET. If not, POST.
But then how are you going to indicate a delete action? Just make up something to stuff in the post body? How is that any better?
URL paths are function names. The arguments to a GET function are query parameters. The arguments to POST functions are a JSON body (or form fields if you’re doing AJAX). You make up requests and responses that fit the domain instead of assuming everything is a resource with the same verbs. I’m also against putting resource IDs into URLs for APIs (you can do it for stuff end users see to make the URLs pretty, but not for APIs).
What does the R stand for
clearly the R stands for RPC ;)
Right tool for the job.
Aren’t you just stating that you prefer RPC, without actually engaging with the argument for hypermedia?
The argument is that “Uniform Interface Constraint” (resources with a standard set of methods) allows you to make general clients that can interact with your resources with no out of band information (like API docs), a la web browsers + html.
Admittedly, what you describe is, in fact, how the majority of most APIs today work, and there is an interesting discussion about why that is if hypermedia supposedly has so many advantages.
I think your argument would be more interesting if you stated why you think that goal doesn’t have value, especially given that the web itself works that way, that it solves problems like API versioning, and so forth.
Why do you not like this specifically, out of curiosity? What do you prefer?
Second question first, resource IDs belong in query parameters. HTTP has many overlapping ways of sending data from client to server and server to client. The client can send information as a method verb, a URL path, a query parameter, a header, or a request body. There has to be some system to organize the arbitrary choices. The system is:
IDs are prettier in the URL path, but for an API, that doesn’t matter. You just need a convention that is easy to follow.
As for Hypermedia, I just care that the website is good for users and developers. Whatever the theory is behind it isn’t very important. It’s great that web browsers are universal tools, but that’s true for JSON APIs too, so “hypermedia-ness” only matters if it makes development easier or harder. I think probably HTMX is easier for most web apps, so that’s why I like it. Even then, I’m more partial to Alpine.JS because I feel like the core motivation for a lot of the HTMX partisans is just wanting to avoid learning JS.
Thanks for explaining.
I know this is a selling point, but fwiw I have a lot of JS experience, consider myself good with it, have used React and other similar frameworks, but still like the simplicity of the old MPA model – htmx being for me just an upgrade. Having just the single data model of the resources on the server to think about it.
Agree with your point about “overlapping ways of sending data from client to server,” and also agree that having any clear system is more important than “the best system,” if there is one. I guess I’m not seeing why the classic system of “url path to describe resource”, “http verb to describe action” is not good enough… It can be stilted and noun-y, yes, but imo that’s not enough reason to throw away a perfectly good existing “system,” as it were.
I don’t like the classic “everything is a noun” system because it ends up needing a lot of requests to get anything done, and requests are the slowest thing you can do with a computer.
I’m working with the MailChimp V3 API this week, and to send a campaign takes three requests: 1. Create campaign 2. Set content 3. Send. In MailChimp API V2, it’s a single request, but they’re finally shutting it down at the end of the month, so I’m being forced to make the change. Because it’s three requests instead of one, I probably need to put it into a queue now because it won’t be reliably fast enough to get done in one request for my users, so now I have to deal with all the complications of asynchrony, and for what? The old API was better.
Seems like a reasonable complaint but orthogonal to the naming/noun-ness of the system. They could continue to support the version you prefer with something like POST “api.mailchimp.com/one-shot-emails” or “outbox” or whatever. That is, from a pure naming persepective, you can always transform back and forth between the two systems.
To your point, classic REST typically has aggregate endpoints return a list of ids, and then you have to make requests (possibly parallel) to each id resource to get the details, which is cumbersome. But nothing forces you to follow that if it doesn’t suit your use-case.
I call this “BrowserTP” since it’s a squished down version of HTTP based on what browsers supported in the early 00’s.
I would say thusly: HTTP is an RPC protocol where the method name (or function or procedure name if you wish) is the method (sometimes called the verb). The URL path is the object that you are calling the method on. The arguments are query string + body as you say.
And sure I can say “please create a deletion for the element in this collection with id 1” it’s not wrong per se, but why wouldn’t I just say “please delete element 1”
because those are part of the HTTP spec and have reasonable meanings useful for implementing resource-oriented url schemes:
DELETE /comments/33
vs
POST /comments/33/delete
I agree that they aren’t really useful, but it takes very little effort for the author to add them and a lot of people want them.
Aside from the obviously minor difference of sending
POST /thing/deletevsDELETE /thing, other HTTP verbs can introduce additional overhead with CORS:- MDN: Cross-Origin Resource Sharing (CORS)
I was going to argue the opposite with approximately the very same line quoted. If you and your webapp rely on the browser for some of the protection against some level of cross-site request forgery attacks, you can use the verbs as they were intended and rely on the browser to enforce them to be usable according to CORS rules.
Guess why https://fetch.spec.whatwg.org/#forbidden-header-name lists the
X-HTTP-Method-Overrideheader (and friends) to forbidden headers in CORS? Lots of vulnerable web pages, that’s why :(CORS still works with GET and POST, it just doesn’t require multiple requests.
I disagree, they actually simplify things by disentangling POST from update and deletion actions.
Edit: in other words, they add a couple terms to our vocabulary…I don’t see how they add an entire layer.
layer is maybe a wrong term (i’m french)
i want to say that it add complexity: if you have a reverse proxy, it has to support the new verbs, if you have logs it should be aware of this verbs, if you have something in your infrastructure which used to ignore DELETE, and suddenly support it, it suddenly delete unwanted things
in case anyone wants to contribute, the hypermedia systems repo is now public:
https://github.com/bigskysoftware/hypermedia-systems
the content of the book is licensed under Creative Commons BY-NC-SA 4.0
https://creativecommons.org/licenses/by-nc-sa/4.0/
all other content is licensed under 0-Clause BSD:
https://opensource.org/licenses/0BSD
hi there, i’m one of the authors of this book
the book was originally set to be published by a big tech publisher, but they backed out so we are releasing the book for free on the web and we are going to try to self-publish it
we are in the process of re-writing the book with a bit more of a conceptual bend than what the publisher wanted, and we are happy with how it is turning out. It is a work in progress, and there are incomplete sections and some repetitive areas, but the structure is about where we want it and much of the content is finished
the book covers hypermedia in general, then htmx for hypermedia-driven web applications, then Hyperview for hypermedia-driven mobile applications
hope people find it useful and interesting
This explanation of the usefulness of
hx-boostis something that had never occurred to me, and I’ve been thinking about (in addition to actually incrementally using it in new things) how HTMX improves my apps’ experience off and on for a few months now:That’s a good point, and might merit mention in the official documentation, because my initial reaction to
hx-boostwas to ignore it because there didn’t seem to be much joy in using AJAX just to transfer the full page anyway. I was mostly thinking in terms of network transfer. I don’t think I’m alone.Does the browser re-process them if those resources are cached and not expired? I don’t think it is any different in that case…
Good question. I haven’t dug into that. Maybe @1cg has?
There’s a reason this sort of thing isn’t mainstream (anymore). “Async transparent” is a synonym for “free-threaded”. If you’re going to have mutable state you need some indicators of where discontinuities in state can happen (i.e., modified by non local code) to make reasoning about your code possible. The other way you can go is the Erlang design where suspending the local stack for IO doesn’t affect reasoning because there’s no local mutable state.
yes, I don’t think async-transparency is a good fit for general purpose programming, but it is nice for front end scripting, and given the already-single-threaded nature of JavaScript, it works pretty well and opens up some nice patterns with respect to event-driven programming that are painful in JavaScript.
a cool example is what we call “The Akşimşek Gambit”, a bit of code that Deniz Akşimşek wrote to make a div draggable:
https://twitter.com/htmx_org/status/1373987721354506243
you can see it in action if you go to the (pretty spartan) demo page and select “Drag”:
https://hyperscript.org/playground/
the crux of the algorithm is this:
where you loop until a pointer up from the document occurs, and then wait in the loop for either a move or pointer up.
Insane, but it works, and it’s pretty darned cool.
Which, come to think of it, is a pretty reasonable description of hyperscript…
My point is that once you add “async transparency” (aka “green threads” or “coroutines”) it’s no longer “single threaded”.
It might be less code for this one application. But I feel like everyone agreed that Angular-style directives have a very low ceiling, and eventually you just want the power of a programming language to generate your actual markup. This way you’re not stuck wading through tons of documentation to figure out the arcane attribute syntax for some hyper-specific use case.
A concrete example of this is polling. Here is the HTMX documentation for polling: https://htmx.org/docs/#polling.
You have to find the specific attribute that you need (
hx-trigger) and then you have to work with the inner scheduling DSL for when to poll (every 2 seconds). What if I want to poll every odd hour? What if I want to poll only on Mondays?I’m sure there’s a place where this is useful, maybe for small applications or side projects. It probably is slightly quicker initially. But I’m not alone in abandoning this style of UI development a long time ago.
For more dynamic polling, I would write a small script to trigger an event, and then listen for that event.
The crux of htmx is hypermedia: exchanging hypermedia with a server and using hypertext as the engine of application state. It will work well for some types of applications, and size is less important than the flavor of the application: gmail would be great as a hypermedia application, google sheets would not. The core question is: can the UX I desire be achieved with hypermedia and my hope is that, with htmx, the answer to that question is “yes” for a larger subset of applications.
I definitely agree that there are appropriate hypermedia applications - for me, it’s static content like blogs. I always classified gmail as the exact kind of application that is not good for hypermedia. In fact, Gmail is the complete poster child for AJAX and SPAs. It’s always referenced as one of the first applications that used the SPA style, and I think that makes total sense.
I think you could build a very nice email client entirely in htmx, using hypermedia clients. I like to mention GMail because it was done as a SPA and, in my opinion, didn’t need to be. Certainly what react was created for, to append a comment to a comment list, didn’t require an SPA. Something like Sheets or Maps, on the other hand, would be hard to implement using the hypermedia network architecture.
In general my hope is to expand the class of applications, dynamism & the general UX level that people feel they can achieve with hypermedia:
https://htmx.org/examples
It’s a mindset change (reversion?), to be sure, but for many applications it can simplify things quite a bit.
This is the exact kind of considerations I’m trying to address with my talk. In the demo part I show a faceted search engine, with a special facet option that updates its results according to a change on server state which is the consequence of a user action elsewhere on the page. Pretty far from “static content”, “small application” or “side project”, don’t you think? It’s the same level of complexity that what you can find on Gmail UI.
Yeah, I tend to prefer Alpine.js because even though it is inspired by Angular/Vue, at the end of the day, it’s just JavaScript. If you wanted to make a polling directive in Alpine, you would just write the normal
window.setIntervalcode for it, instead of going into some “inner platform” language.I guess I’m a little confused as this site looks like some kind of article aggregator.
Why would you have used react for a site like this in the first place?
As they say in the talk, when they were beginning they were told they had to use react for their application to be “modern”. Sadly, many people think that that’s true, and don’t realize that there are hypermedia-oriented options like htmx, unpoly and hotwire that can give you more interactivity within the hypermedia model. So they end up going react, because everyone else is, and that’s what HR hires for.
Did y’all evaluate the different hypermedia oriented frameworks before choosing htmx? Just curious if there are significant differences.
I’m not the speaker, I’m the creator of htmx, so not an unbiased source. :)
David mentions unpoloy and hotwire, two other excellent hypermedia oriented options in his talk, and he uses Stimulus for some javascript (rather than my own hobby horse, https://hyperscript.org) but he didn’t say why he picked htmx.
Generally, I would say:
We chose htmx because of its simplicity (data-attribute driven, very few but very generic features). We evaluated:
Hi there, author of the talk here, sorry for the delay.
Our application is not an article aggregator, it’s much more complex than that: it presents future laws being discussed in French parliament. The right part is the text that is being discussed, and on the left you have the amendments filed by parliamentarians, and which aim to change the text.
But still, you’re right: “Why would you have used react for a site like this in the first place?” is precisely the question I asked when I discovered the modern tools of the hypermedia approach. But not because our application is simple: because the hypermedia approach can achieve a lot more than what most people think. It’s not just for “article aggregators”, “student projects”, “quick prototyping”, “small personal websites” and simple CRUDs. All day long I use professional tools that would benefit the hypermedia approach: Gmail, Sentry, AWS console, and others…
And this is what my talk is about: breaking the FUD spread by some people about what is doable with “old-school” web apps (web pages) and what is not doable with that approach, thus requiring the whole API+SPA stack.
Perhaps a more important change is that the entire team became “full-stack” developers, instead of having a hard front-end/back-end split. That’s huge, in my opinion
agree entirely, splitting on features rather than “which side of the wire” is a huge boost in productivity
One challenge I’ve found in that front is that if you want good frontend developers it’s very hard to find those that are also willing to deal with backend development, or having much of any skill there. There are many good backend developers that are alright at dealing with frontend, but above a certain quality bar it’s basically impossible.
I do think it’s great to be able to have people who can really handle the entire stack, but there are issues with mandating fullstack-ness, so you gotta be a bit careful there. This is “solvable” by pairing people up but then you get into another can of worms based on who you have on the team.
Is that split really front-end vs back-end or infrastructure vs UI? I’ve not done serious web development, but my guess would be that it’s hard to find good interaction specialists but much easier to find people who can write code that runs on either end of a network connection. Are there teams where ‘UI designer’ is a separate role but the engineers work on the whole of the application stack?
So I’ve worked on a team that ended up almost there. There was one “pure” UI designer, and another who was UI design but liked coding. There were a lot of growing pains because he couldn’t properly prototype stuff due to our backend being hard to run for people not used to the terminal.
They both could get work done provided the right tools! But the tooling we had was made (essentially) for backend engineers, so it was a huge amount of friction. That and there was just a different kind of workflow.
But yeah, the overall lesson was that there were people able to do the work we really were missing from the team (remember, the other engineers could write code in both domains! Just the frontend code wasn’t great), but those people could not really work on the team without us adjusting expectations about infra-related demands
How does HTMX make full stack dev any easier? You still need to know about the browser, HTML, forms, etc.
Yes, but we have strong evidence from the old days, pre-SPA frameworks, that server-rendered templates are manageable for developers who also do back end work.
It was only when SPAs and their attendant complexity came along that the split between front-end and back-end became pronounced.
I haven’t observed that at all. Real frontend specialty, like advanced CSS and UX stuff, has always been taken care of by frontend specialists. Everything in between, pretty much anyone can do.
What evidence is that? As amw-zero already said, we’ve always had UI experts for that stuff.
The evidence being that full stack development was a relatively common thing pre-SPA era.
Not saying that there won’t always be designers involved, especially once you start talking about externally facing applications. But htmx puts full stack back on the table as a potential option in a way that SPA libraries and their attendant complexity do not.
TLDR:
Took 2 months (21K LoC, mostly JavaScript)
No reduction in user experience
Reduced LoC by 67% (21,500 LoC to 7200 LoC)
They increased python by 140% (500 LoC to 1200 LoC), good if you prefer python to JS
Reduced JS dependencies by 96% (255 to 9)
Reduced web build time by 88% (40s to 5)
First load time-to-interactive was reduced by 50-60% (from 2-6 seconds to 1-2 seconds)
Much larger data sets were possible than react could handle
Memory usage was reduced by 46% (75MB to 45MB)
These are spectacular numbers that reflect that the application in question is highly amenable to the hypermedia approach.
I wouldn’t expect everyone to see this level of improvement, but at least some web apps would.
Build time might be a bit of a red herring, as I bet it was webpack.
esbuildis absolutely blazing fast and gets rid of that whole axis.I do think that measuring what happens in practice rather than theoretical minimums is good, and like up until recently webpack was unfortunately “the thing”, but at least on that front there are ways to make improvements without having to manipulate the universe
Yes clearly we switched from Webpack to esbuild. But this switch was made possible by having a lot less complicated JS stack.
Thanks for the summary! It’s impressive and I can’t wait to use HTMX on a side project