8 ms·
imo any experienced frontend framework person will be able to pick out the issues with this impl. OP is returning entire strings of HTML (App, Todo, Icon) to re
by swyx 2y ago
imo any experienced frontend framework person will be able to pick out the issues with this impl. OP is returning entire strings of HTML (App, Todo, Icon) to rerender on state changes. this works when 1) you dont care about keeping UI state on the parts that are replaced (incl any stateful children of the UI element that happen to be there in your DOM structure), and 2) when you dont have to update the app in any other places when your state changes. go ahead and build your whole app by replacing innerHtml, frontend frameworks will be right here when you get back from speedrunning the last 10 years.
in other words, this todo app is just about the most complex of a frontend you can easily* build with htmx, i'm afraid. try to fix either 1 or 2 and you end up building components and your own little framework.
as an exercise to demonstrate, try taking OPs code and adding a count of todos on each All/Active/Completed tab that should update every time u add/edit/delete the todos. see how much extra ui code that takes. compare with equivalent [framework of choice] impl (in most it will just involve 1 state update, thats it). this is htmx's explosion of complexity that makes it not [ optimized for change ] (https://overreacted.io/optimized-for-change/ https://overreacted.io/optimized-for-change/). code that is hard to change eventually calcifies and consumes code that is easy to change if you do not consistently garbage collect (nobody does)
i bought the hype too until i tried building something nontrivial in htmx and im afraid the aforementioned islands of interactivity you can build are very very smol islands indeed.
happy to revisit my opinion if there are componentlike design patterns in htmx i am not aware of.
*emphasis on easily; with enough elbow grease u can do anything ofc. but then you fall out of htmx's very narrow [ pit of success ](obligatory codinghorror dot com link)
- aaronbrethorst 2y agoI'm not super-stoked about the idea of building SPAs on top of htmx, but what I have found works incredibly well is to build a traditional MPA (SSR etc), embed islands of interactivity where needed, and where something fancier is really necessary, embed a React or Svelte app into just that one portion of a single page.
- swyx 2y agoyea im not even talking about SPAs in my post, just the complexity explosion that comes with updating state in more than 1 place / preserving ui state in the place that gets rerendered. it blows up in your face quickly if you have even any requirement volatility (https://stackoverflow.blog/2020/02/20/requirements-volatility-is-the-core-problem-of-software-engineering/ https://stackoverflow.blog/2020/02/20/requirements-volatilit...)
- jonathrg 2y agoI agree that it becomes complex if you have state on the frontend. htmx scales better if you keep all or most of your state on the backend. I've found that using the websockets extension really helps with automatically keeping the frontend in sync.
- ctvo 2y ago> I've found that using the websockets extension really helps with automatically keeping the frontend in sync. I choked reading this imagining people thinking they're doing something simple (as in not complex) by introducing websockets so they can keep state in their Go backend and sync it with their front-end, ya know, to keep track of the # of TODOs checked.
- jonathrg 2y agoBut it is simple :) The underlying technology might be more complex, but the library is solid, it's trivial to update any part of the page once you have the libraries set up, and you don't need to write any javascript. Works for me!
- mslip1 2y agoSo I’m building something with HTMX - combining it with alpine has been pretty nice for interactivity managed by client side state
- swyx 2y agoi havent tried the combination - perhaps this is the thing ive been missing. any recommended intro/resource for alpine + htmx that we can browse?
- dimfeld 2y agoGoogle for AHA stack. (Astro, HTMX, Alpine) There was a great site by Flavio Copes that went into a lot of detail on using them together but it looks like it’s gone.
- flaviocopes 2y agoDropped it a couple days ago to revisit it as a blog post, good timing I guess. Restored https://ahastack.dev/ https://ahastack.dev/
- martinbaun 2y agoIt's pretty good combo. I use Alpinejs for the client side interactivty such as modals, but then use htmx for as much as I can that interacts with the backend. You could be using only htmx or only alpine but the combo is really nice
- wk_end 2y agoIt seems like it makes easy things easy and hard things hard, which seems like a pretty poor value proposition - at least relative to some of the hype around it.
- afavour 2y agoI think the takeaway here is "make the easy things easy, don't use it for the hard things". One of the most exhausting things about any discussion about front end web dev is that it gets treated like a monolith. It _can_ be incredibly complicated. In many scenarios that complication is unwarranted. But in some it's justified. Htmx is a poor choice for a full single page app. That's fine. It excels in other areas. Right tool for the right job.
- wk_end 2y agoBut easy things are also relatively easy when using other tools that scale up better. Even if HTMX makes the easy things slightly easier, is that worth investing time and energy into learning it in addition to those tools that scale up better? Is it worth building things with it if I know that months down the line I'm going to need to scrap it once my easy thing becomes slightly less easy? Like I said, this seems like a poor value proposition to me. Of course, if other people are happy with it more power to 'em. To me it feels like people are eager to latch onto this because it's different, and because there's a dopamine hit associated with seeing the easy thing become a little easier when taking a new path that's overoptimized for it - hence the hype - not because it's actually good engineering, in terms of the tradeoffs you're making. Of course, I feel the same way about Tailwind, so maybe I'm just old and grumpy.
- Spivak 2y agoBecause it's a drop-in, no-dependency, no build-step library that can make your static MPA a little less static for the little bits of interactivity you need with not much effort. It's what you reach for to avoid "write the whole website in JS." React -> "The site exists in JS, HTML is just a render target." jQuery -> "Poke at the HTML from JS." Which is brittle as hell. htmx -> "The site exists in HTML, extend HTML to handle the common tasks you want to do with it."
- traverseda 2y ago> when you dont have to update the app in any other places when your state change You can replace elements outside of your direct tree if you want. The simplest case you replace the whole page and pick what elements you actually want to change. You're thinking about HTMX wrong. It's for progressive enhancement, the default is a full page reload and then you progressively enhance parts of the HTML. You should be using the same code paths and template to generate the islands of interactivity as you do for the whole page. You can then optionally send less HTML by just sending the parts that you expect to have actually changed, your "islands".
- LudwigNagasena 2y ago> You can then optionally send less HTML by just sending the parts that you expect to have actually changed, your "islands". And then you end up with modern SSR frameworks that do the bookkeeping for you.
- Imustaskforhelp 2y agoyes but mostly the island architecture is only dominant in the javascript world we can basically get the benefits of spa without having to learn js / use minimal js using htmx in some sense https://github.com/donseba/go-htmx https://github.com/donseba/go-htmx check this out
- dingnuts 2y agoIf you render HTML on the client you still have to render a transport format (usually JSON) on the server side. Sending HTML just lets you skip the transport format and the client side rendering.
- LudwigNagasena 2y agoAnd letting your framework do the bookkeeping for you lets you skip the whole issue. I don't know the exact specification of React Server Component Payload, but I know that it somehow changes stuff on the client-side when the client interacts with the server. (It sends something like `["$","p",null,{"children":["a child","another child"]}]`)
- L3viathan 2y agoWhile I agree with this project being a bad idea, both 1 and 2 are addressed by HTMX itself, via hx-preserve and Out-Of-Bounds swaps.
- swyx 2y agothanks. yeah i will be the first to admit i've only spent like 2 days with htmx so i wont know everything (but still...) re: hx-preserve. what if i want to "conditionally preserve" - preserve this element when my state is one way, but not in other states? i dont see a way. re: hx-swap-oob. looking at https://htmx.org/attributes/hx-swap-oob/ https://htmx.org/attributes/hx-swap-oob/ i think it still does not address what i'm looking for. any master-detail list kind of UI will want updates in 2-3 places when 1 piece of state updates (aka ui consistency, ui as a function of state). i fail to see how attaching an attribute with 1 place for an ID solves that. perhaps theres another api for "multiswap"? even if it existed... idk if i'd be comfortable using it man (ofc, i am clearly biased/taught to "think in components" from 7 years of react exp)
- jdiff 2y agoYou're misunderstanding hx-swap-oob. Each element with that attribute will go and replace the element with the matching ID, keeping them all in sync with one response from the server.
- artificialLimbs 2y ago'preserve this element when my state is one way, but not in other states' You could send the state back to the server with the request and respond appropriately on the backend. Or check in the db without sending it, if it lives in the db (it probably should?).
- jdiff 2y ago> 1) you dont care about keeping UI state on the parts that are replaced (incl any stateful children of the UI element that happen to be there in your DOM structure), and 2) when you dont have to update the app in any other places when your state changes Htmx does have tools for both of these cases. Out of the box, htmx throws out state, but there are plugins such as morphdom-swap for merging in the new DOM fragment into the old while keeping state. I have some client-only state that holds references to DOM elements in Javascript, and by default, yes, htmx breaks all those references as those elements no longer exist. Link in morphdom-swap, and my references live on across reloads, even across attribute and content changes. And for #2, htmx also allows you to swap in elements that are not the target element, just by specifying that that's what you want. IMO these are pretty basic tools of htmx. Like you said, without them about the most complex thing you can create is a to-do list, and sometimes not even that.
- swyx 2y ago> morphdom-swap this https://github.com/bigskysoftware/htmx-extensions/tree/main/src/morphdom-swap https://github.com/bigskysoftware/htmx-extensions/tree/main/... with 159 stars is a basic tool of htmx? is this the community consensus?
- jdiff 2y agoNo. Morph swaps[0] are the basic tool of htmx. Morphdom-swap is simply the one that works for my usecase. [0] https://htmx.org/docs/#morphing https://htmx.org/docs/#morphing
- jonathrg 2y agoParts of htmx were yoinked out of the core library into an extensions repo relatively recently, as part of htmx 2.0. That might explain the relatively lower number of stars. More important than github stars is that it is indeed part of the htmx project and is documented here https://htmx.org/extensions/ https://htmx.org/extensions/
- throwitaway1123 2y agoThe htmx author maintains his own swapping library which has more stars (although I wouldn't judge a project solely based on Github stars): https://github.com/bigskysoftware/idiomorph?tab=readme-ov-file#htmx https://github.com/bigskysoftware/idiomorph?tab=readme-ov-fi...
- stuckinhell 2y agoI agree with you. After seeing some internal prototypes at my job abusing htmx boost. I'm slowly going on the anti-htmx bandwagon. I'm still not pro-react or pro-vue. We need a stabler frontend js framework.
- jerrygenser 2y agoI was just looking into htmx the other day. Came across the following library: https://github.com/iwanalabs/django-htmx-components https://github.com/iwanalabs/django-htmx-components It's an example using django-components. Does this satisfy your comment about component at all?
- mordechai9000 2y agoIn that case, IIUC, state is managed on the server, and the client is only responsible for rendering views generated on the backend and returning user input via form or json. This is what htmx was really designed for, anyway.
- normanthreep 2y ago>smol small. thanks
- low_tech_punk 2y agoThe author swyx is the founder of https://smol.ai/ https://smol.ai/ It's either a typo out of habit, or an intentional reference
- normanthreep 2y agothe word is still spelled "small". fight meme speak
- int_19h 2y agoSo long as people understand it, why should anybody care?
- normanthreep 2y agopeople give me grief all the time because i don't use proper capitalization in my texts. they even ridicule me if i say "you understand what i mean so who cares" but i don't get to do the same thing when they say stupid shit like "smol". that's just normal, while i am retarded
- jpc0 2y agoUsing capitalisation is actually reasonably useful for people with certian classes of disabilities, maybe concider it purely from the perspective. So is breaking up things with whitespace which you did reasonably well. So it's not a matter of "You know what I mean, so who cares?". They may realistically have had to put in significantly more effort into understanding what was written. That isn't entirely true for something silly like the word smol.
- int_19h 2y agoi often avoid capitals myself in informal writing, but to be fair, there's a valid argument that period is pretty small and can be hard to spot by itself for something as important as the statement separator . capital letters help with that somewhat, although it doesn't help that we've overloaded them for other things . putting a space before the period helps keep it more distinct, but i really wish our punctuation was better designed (right after we reform english spelling i guess ...) . but i digress . whataboutism aside, what's the actual problem ?
- tshaddox 2y ago> frontend frameworks will be right here when you get back from speedrunning the last 10 years More like speedrunning the period between 20 years ago and 10 years ago! React is 11 years old, much older than jQuery was when React was initially released.
- evantbyrne 2y agoIn my decades of experience building web applications, I have found it exceedingly rare for components to benefit from SPA-style state management. These frameworks build layers of abstractions to replace functionality that exists in the browser. For example, web forms should never require the level of complexity that frameworks like React steer developers towards: downloading JS components, listening to events to build a local state, crafting an AJAX request, rendering the return JSON as HTML. It almost seems as though there is an entire generation of frontend developers who never learned that there are way simpler alternatives that perform just as well in the real world. htmx might not end up being a SPA-killer, but progressive enhancement has always been a worthy contender.
- davedx 2y agoI don't know about the kind of web apps you've been building, but most of the ones I've built over the last 10-15 years have had too much interactivity to be done with simpler server side rendering.
- evantbyrne 2y agoEverything from MPAs, to SPAs, to animation heavy websites that could only dream on being tailwind. Progressive enhancement doesn't mean giving up on frontend validation, dynamic functionality, and juice. I'm curious what problems you haven't been able to solve without converting whole applications to JSX.
- mplewis 2y agoJust because problems are possible to solve in a hybrid approach doesn’t make the hybrid approach the ideal solution for complicated UI.
- evantbyrne 2y agoMy idea of a complicated UI challenge is not updating DOM in two trees. I have found React to be inadequate for the hardest UI challenges that I've been presented with. Things like DOM manipulation for interactive animations should not be handled by React state updates.
- malkarouri 2y agoHonestly interested in your experience. I am not surprised around (1). HTMX is based on REST, which is by nature based towards having the state in the server and having a stateless client. But what is the advantage of having the state in the client. Isn't that just a bias of the current frameworks? I can see cases where you really need a thick client, and in that case I would use GraphQL rather than REST for those. But, there are quite a few cases that can work with REST and mostly server side. I think (2) is solved by out of band capabilities of HTMX. I don't think that is naturally a limitation of the conceptualisation.
- LegionMammal978 2y agoRegarding state on the client, my general concern is connectivity with the server. If I have a flaky mobile connection, or if I have a really high RTT to the server for any reason, then I don't want UI interactions to start failing or slowing down left and right. Indeed, a lot of the sluggishness I've experienced with others' websites has to do with excessive roundtrips for trivial tasks like clicking around. So I'd prefer to keep most UI state in the client, if nothing else. (Of course it's still quite possible to make excessive roundtrips with an SPA framework, but it naively seems like it's at least more controllable than if everything is rendered server-side.)
- jazzypants 2y agoThe problem is that you need to remember every single place in your app that needs to be updated when you change state instead of your framework doing it for you. You said it yourself-- the "out of band capabilities". Instead of your UI automatically updating in reaction to a state change, you have to manually write out every single component's markup while being extra careful to make sure that each ID matches. [1] This is why HTMX is ultimately an imperative framework. You have to wire everything up manually yourself instead of simply building a declarative representation of your UI and letting your framework handle the synchronization. Did you ever use jQuery? The negative aspects are remarkably similar to the point that it is mildly amusing. 1 - https://htmx.org/attributes/hx-swap-oob/ https://htmx.org/attributes/hx-swap-oob/
- low_tech_punk 2y agoGlad to see you here swyx. I think the issue you outlined is acknowledged by the htmx's authors and addressed in the Morph Swaps documentation: https://htmx.org/docs/#morphing https://htmx.org/docs/#morphing What is ironic though, is that the morphing algorithms are similar to what modern SPA frameworks do, except that it can be addressed without introducing new concepts such as vdom, zones, signal etc. I agree that the island architecture is limiting when it comes to large scale application with state shared across multiple areas in the UI. I'd be curious to hear others finding success in building apps. p.s. I appreciate the smol island :)
- pjs_ 2y agoOn item 2, you can use hx-swap-oob to update as many other parts of the page as you like. That will work great for the count that you propose. https://htmx.org/attributes/hx-swap-oob/ https://htmx.org/attributes/hx-swap-oob/
- yazklok 2y ago[dead]