A modest critique of Htmx

(chrisdone.com)

203 points | by wibwobble12333 11 hours ago ago

67 comments

  • recursivedoubts 10 hours ago ago

    These all look reasonable to me.

    I especially go back and forth on attribute inheritance (it can be disabled via the htmx.config.disableInheritance option)

    Three of the criticisms boil down to the fact that client-side state doesn't always play well w/htmx swaps (especially the simple ones) which is absolutely true.

    And events can get crazy. They are powerful, but crazy and at times hard to debug. Such is event-driven life.

    The one thing I don't agree with is the default queuing mode: it is not to cancel an existing request and replace it. Instead it is to keep the current request in flight and queue one and only one additional request. I'd need to sit down w/them to see if they were misinterpreting something, using the hx-sync attribute to implement the behavior they mention, or if there is a bug.

    I would also like to take this opportunity to market our mug for people who don't like htmx:

    https://swag.htmx.org/products/htmx-sucks-mug

    • ksec 6 hours ago ago

      I just want to say thank you. Not only because of HTMX, but for being a model and showing what proper "Engineering" should be. Knowing trade - offs and accepting the fact no solution is perfect.

      Although that may be because you have a background of Industrial Engineering.

    • Nathanael_M 8 hours ago ago

      Man, you’re everywhere. I have a Montana’s restaurant in my city and I’m scared to go in because of you.

    • heavensteeth an hour ago ago

      I cannot express the pleasure I felt seeing prices in my local currency automatically, without the Shopify "Zoinks! Looks like you're on our American store, would you like to change to our Polish store?" modal I've come to know and hate. Thanks.

      • troupo 30 minutes ago ago

        Often changing to local currency isn't just a straightforward x*(exchange rate). There could be weird taxes applied

    • dullcrisp 9 hours ago ago

      By queue only one additional request, do you mean cancel any existing queued request?

      • recursivedoubts 9 hours ago ago

        the code is a little gnarly, but if you don't specify anything the default behavior is to keep the "last" event that comes in while a request is in flight:

        https://github.com/bigskysoftware/htmx/blob/1242977d11bebe56...

        and that dumps the existing request queue and puts request created by the last event in it by itself:

        https://github.com/bigskysoftware/htmx/blob/1242977d11bebe56...

        we don't cancel the current request or issue the next request until the current request finishes

        but there could be a bug in the code, for sure, it's pretty crazy

        • dullcrisp 9 hours ago ago

          I thought they were complaining that any request is being cancelled by a subsequent one, since they wanted all the requests they made to go through (presumably the requests are altering state?) Probably I misunderstood what was meant by “losing work” though.

        • angra_mainyu 8 hours ago ago

          >https://github.com/bigskysoftware/htmx/blob/1242977d11bebe56...

          This seems to be a scenario where switch/case blocks could make the elif-trees a bit easier to read.

          Also, the code could use some care about not going so deep into the Vs:

              // request headers
              if (requestAttrValues.noHeaders) {
              // ignore all headers
              } else {
                for (const header in headers) {
                  if (headers.hasOwnProperty(header)) {
                    const headerValue = headers[header]
                    safelySetHeaderValue(xhr, header, headerValue)
                  }
                }
              }
          
          could just be:

              // request headers
              if (!requestAttrValues.noHeaders) {
                Object.keys(headers)
                  .filter(hdr => headers.hasOwnProperty(hdr)) 
                  .forEach(hdr => safelySetHeaderValue(xhr, hdr, headers[hdr]));
              }
          
          
          Not even sure if that hasOwnProp check is needed, unless header keys are explicitly set to undef.
          • recursivedoubts 8 hours ago ago

            yeah i prefer just plain ol' if statements, i find them easier to debug

    • nickpeterson 10 hours ago ago

      I’ll definitely pile on with the inheritance causing issues. It made me feel like unsetting them constantly defensively.

  • Havoc 8 hours ago ago

    Not on this in particular but in general: I’ve held off on diving into front end because it’s just such a circus. So many options, so many opinions, so much criticism and then as if that wasn’t enough the whole fkin meta changes monthly. We’re doing react. No actual wasm. Wait no static page. Or maybe htmx. Or vanilla js. Or maybe a mix…well call it remix…it just never ends

    I do believe everyone involved means well and aims for technically strong outputs but my good the end result is still fuckin chaos.

    Backend and systems programming has people with strongly held opinions and flame wars too but somehow it feels more like a war between gentlemen and less The Purge chaos.

    • shepherdjerred 4 hours ago ago

      I just don’t understand this opinion.

      Backend (and frontend!) can be use stable technology choices if you want to. There are also plenty of bleeding edge libraries/frameworks/languages that come out every week.

      As an example, how do you want to deploy your backend? VPS, severless, Kubernetes? What database? Which language? Which libraries?

      There are boring stable answers to the above for backend, just like there are boring stable answers to frontend.

      Really, I think you’ve just found those boring stable options for the backend and you haven’t done that for the frontend yet.

      React has been out for more than a decade and it’s the dominant way of building UIs. And there are pros and cons to this with 1000 solutions, but, really, plain React will work for most things you want to do.

      • WD-42 4 hours ago ago

        What exactly is "plain React" though? Not sure I've ever seen a project that used only React and nothing else. It would seem you'd need a build step, at the minimum.

        • shepherdjerred 4 hours ago ago

          Yes, you would need a build step. create-react-app has existed for a very long time and works quite well though advanced applications tend to outgrow it.

          Alternatives are Webpack (stable, boring), Vite (starting to overtake Webpack since it's significantly simpler), and 1000 other libraries.

          Again, there is some movement here, but Webpack has been in a dominant position for nearly a decade and there's no reason you can't continue to use it today if you value stability. It's the equivalent of choosing to host your backend on a VPS instead of trying out serverless.

          Needing a build step is part of the complexity of frontend. I think frontend is getting much simpler with build tools like Vite and the addition of ES modules. But, even with these new things coming out, you can stick to your boring stable choices on the frontend just like you can on the backend.

          • WD-42 3 hours ago ago

            Yea I'm not really buying it. create-react-app is deprecated. https://react.dev/learn/start-a-new-react-project points you directly at Next.js as a *starting point* and the section about using React without a framework does it's best to discourage you from doing it.

            This is insane for beginners.

          • nsonha 38 minutes ago ago

            You use a lot of words to respond to such a minor point. The main point is that actual "plain react" is useless. You need at least a router, some way to manage state, some way to manage style and so on. It's why nextjs is so popular, they are practically "plain react"

        • roywiggins 4 hours ago ago

          You only really need a build step to use JSX, which is strictly speaking optional.

          • shepherdjerred 4 hours ago ago

            This is true (and part of why I love React/JSX) but in practice nobody writes JSX by hand.

    • cageface 5 hours ago ago

      User interfaces have different, inherent complexity that backend programming doesn't have. If you look at the Android & iOS native toolkits they've churned at least as much in the same time.

      Also, and it seems like this has to be pointed out in every one of these threads, the complexity of interfaces we're building on the web now is far greater than what we were building 10 years ago.

      • mrbombastic 4 hours ago ago

        Not sure why this is downvoted without comment, many people underestimate the complexity here.

        • kitsune_ 28 minutes ago ago

          There indeed is complexity, but a lot of the projects that are created to deal with that complexity that gain traction are made by people who don't have much experience in general, or lack exposure to non-frontend programming, so you end up having to deal with a lot of half-baked stuff. It's kind of a lethal cocktail.

    • eddd-ddde 5 hours ago ago

      This is so true. Anyone trying to learn frontend as a newbie today has an unreasonably hard task at hands. So much unwarranted complexity.

      I feel like the backend is just an inherently simpler problem to solve, request in, response out. Largely stateless. Of course there are harder things to do like stateful 2-way connections, but the solutions are mostly concentrated on a couple of technologies. Like yeah we have stuff like graphql, but at the end of the day the principle is the same.

      • shadow28 5 hours ago ago

        "Backend" is absolutely not a simpler problem to solve, it's an umbrella term encompassing a wide variety of domains. If you're talking specifically about Web backends, then sure, maybe there's a case to be made there.

    • WD-42 5 hours ago ago

      Many others including myself have made this observation. I think I've finally formulated why there seems to be such a stark difference between FE and BE/systems cultures.

      The backend and systems programmers are still writing code in a programming language.

      So much of FE dev now is stringing together other people's declarative frameworks. When programming is done it's mostly glue. So if you exist in this paradigm you're going to have very strong opinions about whatever framework/tech you are using because it's so hard to operate outside of it. You also gain a vested interest in the survival of whatever you've chosen.

      This is why I've been slowly trying to make the transition out of web dev, at least FE. I don't want to deal with this crap anymore!

    • recursivedoubts 7 hours ago ago

      i don't know really what to do about it, but i did write a book on the ideas of hypermedia and how htmx extends them that you can read online for free here:

      https://hypermedia.systems

      i think the ideas of hypermedia are fairly stable and relevant, particularly the concept of a uniform interface, even if htmx is just one implementation of them

    • Jgrubb 7 hours ago ago

      I considered myself a frontend dev 10 years ago, I loved jQuery and Angular 1.x, Sass. I never really caught the Node fever, and it seems like almost everything connected with the JS scene since then has been constant churn and complexity. I moved into infrastructure and data and never looked back.

      That said htmx is the only remotely intriguing development I've seen in frontend dev in a decade.

      • 91bananas 5 hours ago ago

        I too loved jQuery, we've used Vue which is on 3.x now and doesn't really seem like it will change terribly much, in the future. It solves all of the things that in jQuery became really difficult while still feeling like there is still a DOM somewhere in there and we're not all that far removed from jQuery style js. Will agree though, most of the newer frameworks I just don't get.

    • diggan 7 hours ago ago

      > then as if that wasn’t enough the whole fkin meta changes monthly. We’re doing react. No actual wasm. Wait no static page. Or maybe htmx. Or vanilla js. Or maybe a mix…well call it remix…it just never ends

      Who told you to do all those changes? Maybe change who you're listening to, or even better: don't blindly follow what others say/talk about, but listen and think about it thoughtfully instead. Stay on whatever framework/library/platform you want and feel works best for you and your use cases. No one is forcing you to chase the latest trends.

      • jfengel 6 hours ago ago

        True, but it does suck to have backed the wrong horse. You framework/library/platform can rot if nobody else is using it. You can't get away with just ignoring it.

        It helps to pick "boring tech", and hope that what has worked will continue to work. But it's still unpleasant to hear about the X killer every week, when X is your bread and butter.

        • rjh29 4 hours ago ago

          Hasn't Rails been traditional server with patched with dynamic parts since like 2005? I would pick that

        • colordrops 5 hours ago ago

          I've been ignoring frameworks and focusing on mostly vanilla JS and have worked on some of the most interesting and well paying projects for 15 years now. Haven't been following any of the hype, even Typescript. Was forced to do some React/Typescript at work for the first time last year and it was fine. Was able to get up and running in a few days.

    • wvbdmp 7 hours ago ago

      Yes, this is exactly why you choose Htmx. So you can focus on web fundamentals. Reason about HTTP and HTML. Sometimes throw in some vanilla javascript when absolutely necessary. Pull in one or two hand-picked zero-dependency libs for things like drag and drop or a nicer date-picker or something.

    • squidsoup 4 hours ago ago

      > I’ve held off on diving into front end because it’s just such a circus

      Its only a circus if you're constantly chasing the new shiny thing. Many of us have been productively building apps in react for nearly a decade without significant changes in tooling.

      • WD-42 2 hours ago ago

        React how though? Are you raw-doggin React.CreateElement? Doubt it.

        So qualify "building apps in react" with whatever bespoke build system, router, state management, etc combination you are actually using.

        Just because you found yourself a tent inside the circus doesn't mean it's not a circus.

      • andyp-kw 3 hours ago ago

        While I don't think react is the best frontend framework, it has become the industry standard and therefore is the most peaceful approach to building apps in 2024.

      • klysm 4 hours ago ago

        This is the way

  • lucis 9 hours ago ago

    We have been using HTMX to create performant storefronts and the results are satisfactory.

    https://farmrio.deco.site/ is one of the largest clothing retailers in Brazil and all the frontend interactions use HTMX, alongside a partial rendering strategy we developed.

    More info at https://deco.cx/en/blog/htmx-first-class-support

    • s6af7ygt 2 hours ago ago

      The example on the blog post is one of those that makes me severely question HTMX and the stuff that we're doing. Doing HTTP requests to increase a counter, or affecting any local-only state change at all, seems so wild to me.

      • karmarepellent an hour ago ago

        It makes me question what we are doing too. I'm using HTMX extensively at work, but I never use it to only update local state. A few lines of Javscript on the client will do that.

        However I think it's a powerful solution to updating the DOM when state changes on the backend and a roundtrip is required anyway. For that matter the examples on the official project site are better to understand proper use cases for HTMX [0].

        Personally I use Active Search and Edit/Delete Row a lot. While Active Search does not change state in the backend, I found it's still a valid use case for HTMX when searching large data sets, since the backend is (in my case) just way faster to search through a large data set.

        It all comes down to your ability as a developer to find the proper solution to the problem at hand. A counter does not need HTMX.

        [0] https://htmx.org/examples/

    • lelandfe 8 hours ago ago

      Love how good the CLS is. I wonder if you can deal with flashes of white during navigation with the new View Transitions API

    • boredtofears 4 hours ago ago

      I'm not sure this is htmx's fault but I wouldn't exactly describe that as snappy

      • heavensteeth 42 minutes ago ago

        I thought that too, but whole page loads are slow too; I assume it's just because I live nowhere near Brazil.

  • dfabulich 8 hours ago ago

    This "HTMX in React" idea just reinvented React Server Components. https://react.dev/reference/rsc/server-components

    An attractive future direction might be to re-implement Htmx in React:

    The server sends a JSON blob that React converts into virtual DOM components.

    That would solve the component state problem.

    It would mean we require no special bridge to use React components.

    It would let us use our React-connected web fetching library, and carefully avoid the queuing choices made by Htmx.

    It would solve the morphdom problems and browser DOM input elements problem, too, which is pretty much a solved problem in React.

    In this way, we could drop the Htmx dependency but retain the benefits of the idea. That is, given a budget to embark on such a big piece of work.

    RSC is still experimental, and the default implementation assumes that you're going to run JS on the server, which undermines some of the point of HTMX.

    But someday (likely in the next year or so) the RSC wire format will be standardized, and then any language can generate RSC JSON for React to consume.

  • sauercrowd 9 hours ago ago

    > The default queuing mode is bonkers

    > By default, Htmx will cancel requests that are in-flight if you trigger another request on the same queue (element).

    This seems like the only default that's reasonable to me

    don't know if the author has a specific example in mind, but if a user submits an input, changes that input mid-request and submits again the request needs to be cancelled, otherwise the UI will be inconsistent by showing a response to an outdated input

    Just processing one response after the other won't be possible if a response swaps out content with different IDs, so a second response won't be able to be swapped out in the same way

  • stavros 8 hours ago ago

    > An attractive future direction might be to re-implement Htmx in React: The server sends a JSON blob that React converts into virtual DOM components.

    Isn't this exactly what HTMX was replacing? The client needing to have a ton of logic and state?

    • klysm 3 hours ago ago

      Turns out there’s good reasons to do that

      • nsonha 31 minutes ago ago

        Only veteran web devs are able to come up with such a bonker idea that not managing state explicitly is somehow better. That's just basic programming but I guess they don't need that to write html.

  • hahahacorn 9 hours ago ago

    Is there an equivalent to Turbo Mount for Htmx? https://evilmartians.com/chronicles/the-art-of-turbo-mount-h...

    I think it's one of the best ways to use Hotwire/Turbo. Default to Hotwire to whatever degree of understanding you have, and as soon as it feels like HTMX/Hotwire isn't the right tool, you can easily switch to your framework of choice.

    • sauercrowd 9 hours ago ago

      Very much agree with you on this - htmx (turbo, hotwire, alpine,...) are not trying to replace all your client side logic.

      It's a spectrum of interactivity, and we should try to pick the best (whatever that may mean) tool possible for the job - sometimes that's hx-boosted links, sometimes it's a react app

    • pier25 7 hours ago ago

      what about using web components?

  • jasoncartwright 9 hours ago ago

    After hearing about it for years, and it apparently being popular in the Django community, I tried htmx for the first time just this morning on a very simple task in an admin interface.

    It's easy to put unobtrusively in place, fun to play with, and it worked. Reminded me of using jQuery for the first time. Would I use it for a complex and involved project? Initial impressions suggest probably not.

  • JodieBenitez 32 minutes ago ago

    Comments about HTMX vs. React keep popping up, but I think they miss the point and it's probably a "marketing" problem on HTMX side if people feel the need to write these.

    On the contrary, Unpoly -which shares similarities with HTMX but is probably more high level- makes it very clear on its front page:

        Progressive enhancement for HTML
    
        Get powerful new HTML attributes to build dynamic UI on the server.
        Works with any language. Gracefully degrades without JavaScript.
    
    Granted, HTMX has "high power tools for HTML" right on its front page, but it also has "reduced code base sizes by 67% when compared with react".

    Anyway, as always, tools ad trade-offs...

  • yawaramin 9 hours ago ago

    > React and Htmx do not interact nicely.

    I want to dig into this a bit. React of course maintains its own rendered part of the DOM and htmx trying to reach into and change any part of that DOM is not going to go over well. It's just going to be replaced with React's rendering again on the next render cycle.

    htmx provides two points at which it can interact with other libraries or frameworks: DOM events and CSS classes. I don't see any problem with classes, but React's synthetic events would probably not work well with htmx (or any other non-React library really). Maybe frameworks like Preact which use real DOM events would work better.

  • manchmalscott 2 hours ago ago

    That last point about dropping HTMX as a dependency but keeping the benefits is why I personally find Phoenix liveview so compelling.

    • ipnon 2 hours ago ago

      Yes, I'm all in on Phoenix and LiveView because of this.

  • ricardobeat 10 hours ago ago

    > Even morphdom overwrites some things you’d expect it not to, so we had to patch it to avoid messing with input elements, and details elements.

    Would love to hear more about this issue. Preserving the state of elements like input or detail is the main function of libraries like morphdom, something must have gone wrong there.

    • recursivedoubts 10 hours ago ago

      at the end of the day morphdom (and my own algorithm, idiomorph) can only do so much, because the current DOM APIs nuke much of the state of nodes when they disconnect from the DOM

      if you look at the algorithms they give up very quickly and simply merge the new nodes in once matching doesn't work at a certain level because of this

      there is a new API coming down the pipe, moveBefore(), that will allow much better morphing/preservation in general:

      https://github.com/noamr/dom/blob/spm-explainer/moveBefore-e...

      htmx supports it today if you enable it in chrome canary:

      https://htmx.org/examples/move-before/

  • dsego 9 hours ago ago

    > Htmx-in-React?: The server sends a JSON blob that React converts into virtual DOM components.

    The author should try inertia.js, it has server-side routing and react templates.

  • andrewmcwatters 8 hours ago ago

    Totally disagree with state in the DOM. It’s natively where it exists.

    • steve_adams_86 5 hours ago ago

      Also in the URL. Both are totally okay, and even desirable. We’ve become so accustomed to managing state in abstractions of the DOM that this seems like a crazy idea, but it has led to all kinds of pain points from complexity to, well, the DOM and URL not always reflecting the state of the application accurately. It’s pretty awful.

      The better we can keep state out of abstractions without losing maintainability or performance, the better.

  • wetpaws 9 hours ago ago

    As a former PHP dev it's fun to see people reinventing the same wheels and hitting the same pitfalls industry solved 2 decades ago.