Remix.run Logo
lbreakjai 4 days ago

Splitting application API and generic data API is orthogonal to HTMX. You still have issues compared to plain JSON, don't you?

Imagine you need firstName/email in once place, firstName/email in another, and firstName/D.O.B in another.

In a plain JSON world, I'd craft a single "user" endpoint, returning those three datapoints, and I would let the frontend handle it. My understanding is with HTMX, I'd have to craft (and maintain/test) three different endpoints, one per component.

I feel like you would quickly end up in a combinatorial explosion for anything but the simplest page. I really don't get the appeal at all. Of course everything can be very simple and lightweight if you hide the complexity under the bed!

listenallyall 3 days ago | parent | next [-]

> let the frontend handle it

via 3 different rendering logic, (such as JSX templates) same as the server

> if you hide the complexity under the bed!

which is what you just did by dismissing the reality that client-side requires the same 3 renderers that server-side requires! (plus serialization and deserialization logic - not a big deal with your simple example but can be a major bottleneck with complex, nested, native objects)

lbreakjai 3 days ago | parent [-]

This isn't about the number of rendering logics. You'll have as many as you have variants, that's tautological. This is about where they happen.

In a classic app, there's one entity that keeps the state (the server), and one entity that keeps how it is rendered. This is very easy to reason about, and the contract is very clear. If I want to understand what happens, then I can open my frontend app and see "Hello <b>{{name}}</b>".

In HTMX, the logic is spread. What I see is a construct that says "Replace this with the mystery meat from the backend, whatever that is".

Assume there's a styling issue. The name looks too big. Is it because the frontend is adding a style that cascades, or is it because the backend returns markup with a class? Now any issue has an extra level of indirection, because you've spread your rendering logic into two places.

> which is what you just did by dismissing the reality that client-side requires the same 3 renderers that server-side requires!

But what's complex isn't the number of renderers, it's where the logic happens. The HTMX website is full of examples where the header of a table is rendered in the frontend, and the body is rendered in the backend. How's that considered sane when changing the order of the columns turns into a real ordeal?

listenallyall 3 days ago | parent [-]

> If I want to understand what happens, then I can open my frontend app and see "Hello <b>{{name}}</b>".

> In HTMX, the logic is spread

I disagree... with React, by definition, the logic is spread. Persistent data, and usually, business logic, is in some data store accessible via the app backend. And then a totally different entity, the front-end, renders that data (often implementing additional business logic) and manages state (which is often not yet recorded in the data store until various updates can be performed).

HTMX helps keep everything aligned. All the rendering logic is right there along with the data and the business logic. If I'm looking for a renderer, not only is it easy to find the template that produced "Hello <b>{{name}}</b>" but it is also easy to find the source of {{name}}. Which also makes it easy to alter {{name}}, say, from Smith, John to Mr. John Smith - because the data store and business logic are right there, it is low effort to switch the order and to begin including the salutation.

Your "front-end" is still all in one place, except it's on the server, and typically rendered via templates instead of React components. But the templates can often access native objects (including their properties and functions) instead of solely relying on JSON objects.

This comment is already long but regarding data tables... yea, highly dynamic pure data-based UI's such as charts and tables aren't HTMX's forte. But even then there are ways... the data- attribute is very useful, and since you are already using JS to handle sorting, filtering, re-ordering, showing tooltips, etc, it's very possible to render valid HTML fragments that can be properly rendered via that same JS (or contain data which can be).

recursivedoubts 4 days ago | parent | prev | next [-]

¯\_(ツ)_/¯

any factoring you do on the front end you can do on the back end too, there's nothing magic about it and you don't need different end points: that can be a query parameter or whatever (if it's even a request, in most hypermedia-based apps you'd just render what you need when you need it inline with a larger request)

it's a different way of organizing things, but there are plenty of tools for organizing hypermedia on the server well, you just need to learn and use them

array_key_first 3 days ago | parent | prev [-]

> n a plain JSON world, I'd craft a single "user" endpoint, returning those three datapoints, and I would let the frontend handle it.

The main problem is that this is extremely, extremely expensive in practice. You end up in Big Webapp hell where you're returning 4mb of data to display a 10 byte string on the top right of the screen with the user's name. And then you need to do this for ALL objects.

What happens if a very simple page needs tiny bits of data from numerous objects? It's slow as all hell, and now your page takes 10 seconds to load on mobile. If you just rendered it server-side, all the data is in reach and you just... use what you need.

And that's not even taking into account the complexity. Everything becomes much more complex because the backend returns everything. You need X + 1, but you have to deal with X + 1,000.

And then simple optimization techniques just fall flat on their face, too. What if we want to do a batch update? Tsk tsk, that's not RESTful. No, instead send out 100 requests.

What about long running tasks? Maybe report generation? Tsk tsk, that's not RESTful. No, generate the report on the frontend using a bajillion different objects from god knows where across the backend. Does it even make sense with the state and constraints of the data? Probably not, that's done at a DB level and you're just throwing all that away to return JSON.

I mean, consider such a simple problem. I have a User object, the user has a key which identifies their orders, and each order has a key which identifies the products in that order. Backend-driven? Just throw that in HTML, boom, 100 lines of code.

RESTful design? First query for the User object. Then, extract their orders. Then, query for the order object. For each of those, query for their products. Now, reconstruct the relationship on the frontend, being careful to match the semantics of the data. If you don't, then your frontend is lying and you will try to persist something you can't, or display things in a way they aren't stored.

The backend went from one query to multiple endpoints, multiple queries, and 10x the amount of code. The frontend ballooned, too, and we're now essentially doing poor man's SQL in JS. But does the frontend team gets the bliss of not dealing with the backend? No, actually - because they need to check the database and backend code to make sure their semantics match the real application semantics.

lbreakjai 3 days ago | parent [-]

> What happens if a very simple page needs tiny bits of data from numerous objects? It's slow as all hell, and now your page takes 10 seconds to load on mobile. If you just rendered it server-side, all the data is in reach and you just... use what you need.

You went on a long tirade against REST, which nobody mentioned. Just ... write an endpoint returning the data you need, as JSON? But write it once, instead of once per view variant?

> Just throw that in HTML, boom, 100 lines of code.

Now you need the exact same data but displayed differently. Boom, another 100 lines of code? Multiply by the number of times you need that same data? Boom indeed, it just blew up.

array_key_first 3 days ago | parent [-]

> Now you need the exact same data but displayed differently. Boom, another 100 lines of code? Multiply by the number of times you need that same data? Boom indeed, it just blew up.

It isn't 2004 anymore - all of the server-side frameworks have components.

Except, now instead of using serialization and JSON, it's a real API. In code. I can click and go to definition.

> Just ... write an endpoint returning the data you need, as JSON? But write it once, instead of once per view variant?

What you just said directly contradicts itself.

If each view variant needs slightly different data, or ordering, or whatever, we now need to make N APIs. Or we don't. And now we're back at square one and everything I said is valid.

The more modular and reusable your API is, the less performant it will be and the more bugs it will introduce. I'm all for the God API that has 1 million endpoints each doing one specific thing. But it seems nobody else is, so instead we get the fucked ass RESTful APIs that are so bad and lead to such overly complex code were pushed to write critical CVEs to avoid them (looking at you, NEXT)