(And don't start with "it's faster/more efficient", that comparison isn't terribly valid because the inefficiencies seen with React/Vue are largely an artifact of bad code/practices, not the libraries themselves.)
> All 3 require some form of JavaScript library coupled with markup to build interfaces.
With HTMX you're typically including one static javascript file that you just download, you're not using any kind of javascript build system at all. Where it has very limited scope it's possible to imagine a browser that doesn't have javascript but that has HTMX built in.
Calling it a javascript library might be a bit much, I mean you're not typically installing this with node/npm, or minifying it, or importing it. You're just including it in a script tag at the bottom of your site. While they both do technically run on javascript I think they have more differences than things they have in common, and saying "Well they're both just javascript libraries" is a very sophomoric take. I mean you might as well just say that all javascript libraries are the same, and it doesn't matter what you use. So why choose react/vue over jquery?
> inefficiencies seen with React/Vue are largely an artifact of bad code/practices, not the libraries themselves.
Ehh, I'm sure you can make a fast bug-free website in server-side assembly if you're so inclined but it's probably not the right tool for the job. The question is what kind of design patterns do the libraries/tools encourage, not "can I do X with Y".
- [1] https://vuejs.org/guide/quick-start.html#without-build-tools
- [2] https://blog.jim-nielsen.com/2020/react-without-build-tools/
Instead of api models and client models, you just have models.
Instead of api routes and client routes, you just have routes.
Instead of unit testing api and client, you test one project.
Instead of having the client making N requests to load all the data it needs from the server (and being careful not to return more data than you need for performance reasons), you return an html with all the data it needs in a single request, and nothing more.
In the case of client stacks using SSR (like Next/Nuxt):
Instead of running the SPA on the server so the server returns the html rendered, you just make the server return the html rendered.
The benefit to the developer is higher productivity. The benefit to the end user should follow from that.
Also, by eliminating application javascript, it allows you to spend more time in your preferred language on the back end.
The downside is the same as regular HTML, although less pronounced: since you are driving application state through hypermedia (HATEOAS), the less coarse-grained your state or UI gets the more annoying things are going to be. There are some patterns that help but eventually, if you want to update 12 different places in your UI at once on every keystroke, the hypermedia approach just isn't going to cut it.
But these days (using transpilers and/or WebAssembly) you can choose just about any language on the front-end ...
Imagine not having html at all. You'd have to create pages from scratch imperatively by doing things like let element = createElement("p"); element.setContent("my paragraph"); parent.addChild(element); It'd be really ugly, a PITA to change stuff and error-prone. htmx is the opposite of that. It tries to make web development declarative again, among other things.
It kind of returns to the original intention of the web.
I know my alternative approach, htmx-enhanced hypermedia, isn't right for every application, but it can be a much simpler approach for many applications, and, since it is so simple, can be used to conserve complexity in applications that have parts that are not amenable to the hypermedia approach.
I share your sentiments about SPAs, and I've been trying to get back to a simpler web stack.
One of the hurdles I keep running into with libraries like htmx and Alpine is that they don't play nicely with Content Security Policy. And I'm reluctant to forfeit CSP to use a JS library since CSP is the most robust solution I've found for preventing XSS.
Alpine is working on a CSP-compatible build, but it hasn't been released[0] and doesn't seem to be a priority.
htmx is compatible with CSP, but it effectively reverses the protection it offers. The attacker can inject JS through htmx directives.[1] I know there's hx-disable, but this degrades CSP's effect from "secure by default" to "secure when the developer remembers to mark the subtree as containing user-controlled data."
Is there a way to use htmx without forfeiting the benefits of CSP?
[0] https://github.com/alpinejs/alpine/issues/237#issuecomment-9...
which, I think should be the case: I don't think htmx should have to exist, I think this is just how HTML should work. That could address a lot of accessibility and progressive enhancment issues as well.
I also pronounce it S P A, so "an" seemed immediately correct to me.
Why would you need JS at all for a date picker?!
A couple of things I had to handle in the last couple of weeks: - Handling different separators for input - having a clear button to indicate "no date" - display the date in a different format
Instead of HTML, CSS, JS in that order maybe they got chucked right into a NextJS / Tailwind twitter clone course as their intro to web dev.
<html> <body> <div>Account number: 12345</div> <div>Balance: $100.00 USD</div> <div>Links: <a href="/accounts/12345/deposits">deposits</a> <a href="/accounts/12345/withdrawals">withdrawals</a> <a href="/accounts/12345/transfers">transfers</a> <a href="/accounts/12345/close-requests">close-requests</a> </div> <body> </html>
What I don't get is who says I want to have all of that html displayed in this exact form anywhere I make a request for account info? Say I want to only display the Account balance - are you telling me client has to cut and parse the html response for that? How much html parsing is that gonna be all over a web page?
Also the example I gave below about setting the css classes and ids inside the returned html elements...
React & Angular do scale this far, I have yet to encounter any who works with Vue that ships over a million lines of deployed code though I'd love to hear from you!
htmx would probably work great for something like GMail, but would be a bad choice for something like Google Sheets. Both are big apps, but one is more amenable to coarse grain HTTP requests because the UI isn't as interdependent.
Interestingly, I have seen a new app that provides a sheet with HTMX: https://www.licenseprompt.com/ (gif: https://twitter.com/WimpieNortje/status/1520419150245638144)
You're saying "I have all this code, what do I do with all this code." The answer is: don't write it!
I never done it with Vue (largest Vue app I ever worked on had roughly 200K lines of deployed code, all in, for the application, very thick client type stuff), but maybe with Vue 3 and the composition API this isn't an issue (I don't think Vue 2 would ever scale well developer experience wise this way)
I'm not throwing shade on HTMX, but there tends to be this energy around it that would make someone who, perhaps trying to weigh some options, stumbles across HN, sees threads like this and thinks oh gee! This sounds great without knowing exactly what that means. And it is true, that perhaps, that person is building app that needs scalable reactivity and fine-grained control, or something along those lines. I at least want to give a fair take on purpose for people thinking about it.
HTMX is great for its target audience, much superior to jQuery in this day and age, but you have to understand what its for.
From the user point of view, I think there are two main types of experiences on the Web:
a ) Interactive documents. Basically web 1.0 but today we want fancier transitions and interactions. This can be provided by htmx and should always have been developed declaratively. It should ideally be provided by the browser and htmx shouldn't need to exist. Examples of this are Gmail and most social networks and forums including this one.
b) Desktop apps-but-I-don't-want-to-have-to-install-them. This would be things like Google Docs, Photopea and most real-time games. To deliver this, right now we have a browser that has become almost an OS inside an OS, to the point only Google can keep up with the complexity. On top of that, we pretend apps are documents and for all the imperative code we need we use a scripting language that was not meant for that, and we need a really complex VM just to keep it more or less performant. For this use case I think at some point we should move all the way into just delivering apps, if not native apps, something like wasm, where the browser tab would just be a vm player.
Rich Harris speaks towards that here: https://www.youtube.com/watch?v=860d8usGC0o
E-commerce stores have different interactivity needs than blogs, which have different needs than documentation, which has different needs than dashboards, which have different needs than real-time collaboration tools, and on and on and on.
Much of the framework angst is around the assumption of a singular tool for all these varieties of interaction and the annoyance that comes with not acknowledging the trade-offs.
Plus the web itself is changing, so the breadth of this spectrum is increasing. Years ago, the ends might not have been very far apart but they are diverging more with each new use-case and app idea.
In the system I've used a mix of regular django templates, some Django unicorn, some HTMX, and some HTMX+Alpinejs
I pick the tool based on the the amount of interactivity I need on the page.
It's.... interesting. If you start out knowing you will do HTMX, then I found everything is much easier. Splitting off small small views to return just the right html after a hx-post is more labor intenstive than i would like, bit overall it's nice.
The hardest part I found was being able to have a fine level of control around the user experience, and solving that required adding a lot of javascript, which made me wonder if it was worth the effort and should have instead just used Vue to handle it.
I've ended up using a lot of HX-Refresh in responses (causes a page refresh) because it was easier to do that than to ensure all the different parts of the page updated at the right time.
The way it cascades htmx values down the tree is really handy, and lends itself to consise attributes on the html.
Overall I'd give it a silver-coated bullet rating. Certainly not a solid silver bullet. :)
This was almost exactly my first impression of HTMX as well. It's a huge step forward! However, for my tastes it demands too many tiny views and micromanaging, which somewhat felt like a drag on my productivity. For an alternative, take a look at Unpoly [1] which has more batteries included (i.e. create layers of interactivity that update lower layers automatically) and is centered around full page requests/diffs and less focused on injecting small page fragments everywhere. For my small apps, I could do everything in one view that took three or more views with HTMX. I can only imagine the views exploding for a modestly complex site. The biggest penalty for Unpoly is that it is quite a bit (~2X) slower than HTMX, which needs to be kept in mind and managed for larger pages with a lot of interactivity. I suspect this is because Unpoly loads the entire page and does a DOM diff to see what it needs to update, as opposed to injecting just a page fragment. In my tests, I was able to manage around this issue using layers. The big upside to Unpoly is that the full page refresh architecture aligns very neatly with Django's request/response cycle, which gives you pretty seamless interactivity and form validation. It also has a lot of batteries included that HTMX lacks. I think HTMX is terrific and revolutionary, but Unpoly fits my brain better while doing Django development.
I found out putting the ids for the htmx snippets in a typed datastructure (in my case Python with type annotations, since I use django in the backend) to be easier to find the corresponding templates, see all usages, etc. I think otherwise it gets a bit confusing.
It provides a smooth UX by fetching next page's HTML in background, then replace the DOM by compareing the diff in HTML. So you won't see a blank page while navigating between pages.
They turned Turbolinks and extended it into a complete framework. I really want to give it a try.
Things I remember from the last time I had to deal with these libraries were redirects and hard-to-debug JavaScript issues due to so much JavaScript relying on document ready/onload events.
Occasionally you get a head nod in the direction that “sometimes, React is the best tool” but most of the time it’s Simpsons memes stoking a culture war.
If you’ve worked in an org where someone with decision making power has drunk the “progressive enhancement not SPA” koolaid, then it’s just as bad as someone who has drunken the SPA always koolaid - at least you’ll find it easy to hire and find support/libraries with the latter.
Not just programming or math, in physiology you have entire research groups worked up about a molecule that causes dementia and after decades of research realise that the story was a lot more complicated than that.
You can almost recognise a healthy mind by the lack of such dogma, just don't make it a rule that would defeat its purpose.
The real sweet spot is it allows you to push server side frameworks like Django even further. You may find you can skip the SPA all together. And nothing beats the speed of development of a Django/Rails/Laravel.
Htmx is part of my go to stack for solo/side projects and my preferred stack on the job for crud heavy line of business applications.
http://youtube.github.io/spfjs/
SPF was a bit more focused on being easy to merge into an existing server side app.
I am glad to see this and hope it has some legs. It could help free us from the need to write every UI in JavaScript(ish).
htmx is more light weight, and very actively maintained.
Why should only <a> and <form> be able to make HTTP requests?
Why should only click & submit events trigger them?
Why should only GET & POST methods be available?
Why should you only be able to replace the entire screen?
By removing these arbitrary constraints, htmx completes HTML as a hypertext
I think the first three items are minor issues, at best, which in no way justify yet another DSL.The fourth is a reasonable point -- it's quite common that you only want to update a portion of a page.
But it's very unclear that HTTP requests are the way to do it.
For one thing, using HTTP requests as the transport for app event handling adds nothing conceptually. It seems nice to use something that people are widely familiar with to build an event model on top of, but HTTP isn't a good fit for everything. So you either need something else (javascript or another language/api/framework) or you awkwardly fit everything into this model anyway.
But more importantly, it implies a strongly hierarchical structure to your app UI, which I think is overly rigid and unrealistic. Content tends to be largely hierarchical, but frequently important cross-cutting concerns pop up... maybe not on day one, but maybe on day 100 or 1000. Now you're swimming upstream.
Also, it's not like there aren't a very high number of HTML-centric options available. It has an interesting low-level approach, but in the end we're developing apps and UIs. It's very unclear to me whether htmx really offers advantages that other approaches don't meet or exceed.
You say what is the advantage before :) :
> ... maybe not on day one, but maybe on day 100 or 1000.
That is the thing. Is Wonderfull when you actually wait and see if you truly need the extra complexity of things.
Go nuts when is time to go nuts.
But is nuts to do it now.
What tires me is the groupthink around web development. SPAs and server rendered content aren't better than one another. It's annoying and unreasonable that the current trend is that SPAs are bad. They are not. Everything bad with SPAs I've seen is caused by developers not getting their priorities straight and by bandwagoning. Stop making webpages complicated and you'll find that many problems disappear.
But to me, writing my markup in JSX (really, TSX with TypeScript) and using scoped CSS solutions was too good to pass up. I just couldn't bear writing text-based templates.
That's why I built Reactivated: combining the best of both worlds. Server-rendered, simple markup — albeit still in TypeScript — but you can add interactivity as needed.
Of course, HTMX is far less opinionated and framework-agnostic. So it can be used with any number of libraries / stacks.
[1] https://www.reactivated.io
[2] https://www.reactivated.io/documentation/philosophy-goals/#t...
[3] https://www.reactivated.io/documentation/philosophy-goals/#r...
[4] https://htmx.org/essays/how-did-rest-come-to-mean-the-opposi...
Make sure to check other essays at https://htmx.org/talk/ (scroll down for Essays)
[Tetra](https://www.tetraframework.com/) might be an alternative if you’re hell-bent on not using React.
But, if you want to ship quick, have a maintainable codebase in a technology a lot of devs are familiar with and have the power to instantly ship for mobile (and buy yourself some time to build one in React Native; code is going to be similar to React.js), I’d recommend using React.
You can use Capacitor.js for instantly shipping a mobile app with your codebase that “just works”. Use Capgo for affordable codepush and you’re set!
HTMX all the way if you’re not building an app cause not everything is an “app”.
At the same time, if you’re building an app with a framework unlike Phoenix, I don’t see why one would not go ahead and use a decent JS framework. Using frontend framework seems to be facing a lot of aversion and I don’t understand if it’s because of the inability to learn these frameworks or what.
Point is, your users just need a snappy app that works. That’s it! And using a robust frontend framework makes it easier.
Great TTFB as I don't need to send it to node to render js, faster navigation for many users with slow plugins and easy to implement.
This seems to do the same thing, and much more. I really need to try htmx, looks cool!