But there are many others. Not sure I understand the point of async rendering, unless you want to mix IO with rendering? Which feels a bit too close to old PHP+html for my blood.
Not clear why HTML rendering needed to be infected with async. None of the example code has a clear need for async - even the `is_admin()` method would be a prefetched property in any reasonable database model.
Your counterpoint still naturally involves something like async _somewhere_ (your proposal is just to move it out of the HTML rendering and into an initial data-gathering stage). If you accept that premise then the question is just where the async code goes.
While on some level it makes sense for HTML rendering to be a pure function where the inputs are gathered from elsewhere (potentially asynchronously), it looks like htmy wants to make it easy to define hierarchies of components. Instead of `is_admin()`, imagine a dashboard whose layout is stored in a database, supporting configurable charts of various flavors. The heterogeneity of the data supporting different types of charts makes it hard to efficiently pull data in a single SQL query (equivalently, any reasonable database model), so somewhere in your code you're pulling a bunch of data asynchronously, and somewhere else you're rendering it. The question, still, is "where?"
Going back to the idea of htmy defining hierarchies of components, imagine how annoying it would be to have to manually grab all the data for a "reporting page" component only to feed it straight back into the renderer -- either having to duplicate the hierarchial structure when feeding data into the renderer (a technique some UI libraries employ, though I don't like it) -- or having to come up with a method for flattening that hierarchy when instantiating the component (another technique some UI libraries employ, one I like more for small projects and less for large ones).
They solve that (to the extent that you think it needs solving) by bundling all that background logic into the components themselves. Did they really need to implement that recursively instead of just walking the hierarchy, gathering the data up-front, and populating it? Eh. The code winds up being similar either way, and either way it definitely forces async back into the middle of HTML rendering.
Mind you, that tends to either make some applications hard to build or to cause the framework to explode in complexity over time as people need new and new ways to say "yes, re-render this thing; no, re-render that other thing, but don't grab its data, ...." There's enough less particularly annoying code involved though that fat, smart components are a natural place for people to gravitate.
Unrelated to htmy completely, a technique I like from time to time even for problems which don't need async per se (and I'm usually using lower-level languages, so the implementation is some sort of more manual continuation pattern, but all those things are basically async, so I won't dwell on the details) is explicitly designing pausable/restartable structures for long-running computations. It's about as easy to write as purely iterative code, and you can run the result as purely iterative with no runtime overhead, so the downsides are low. It opens the door though to easily tuning how long you defer invariant maintenance (too infrequent and your algorithm devolves to the slow thing it's replacing, too frequent and the overhead isn't worth it), easily checkpointing a computation, adding other custom runners for an algorithm (like animating its progress), .... I can absolutely see a use-case for wanting to visualize each step of an HTML rendering, or log OS network counters after each step, and so on. Python's async isn't really the right tool for the job for that (it's hard to modify the runtime to support them without building quite a lot of nonsense from scratch), but async in the abstract isn't bad at all per se.
I was looking for something like this a few weeks ago. I typically use Django and hate the template engines limitations. I needed to make some reusable components and the best option available was switching to jinja to get their macro support, bleh.
This reminds me of the best part of Flutter UI composition, but in a language I always return to.
Have you done any benchmarking? I don't even know what the comparison would be.
In the real world, for web things, people use django or fastapi. I'd suggest picking a project with lots of stackoverflow questions and poking around their docs to see which makes you the most comfortable. Personally I tend to favor litestar these days since it has good docs and issues don't sit around for years waiting on one dude to merge prs (fastapi) and it's a lot nicer than django (and I hate django docs).
Flask/quart are painful to work with due to horrible documentation in my experience, but they're popular too. Quart is just an async rewrite of flask by the same owners.
I think the “rule of thumb” is that none of them are better than using HTMX with templates. HTMX obviously having some limits in terms of security and complex REBAC.
There's a bunch of these kinds of html renderers. Here's mine: https://pypi.org/project/simple-html/
But there are many others. Not sure I understand the point of async rendering, unless you want to mix IO with rendering? Which feels a bit too close to old PHP+html for my blood.
Not clear why HTML rendering needed to be infected with async. None of the example code has a clear need for async - even the `is_admin()` method would be a prefetched property in any reasonable database model.
Your counterpoint still naturally involves something like async _somewhere_ (your proposal is just to move it out of the HTML rendering and into an initial data-gathering stage). If you accept that premise then the question is just where the async code goes.
While on some level it makes sense for HTML rendering to be a pure function where the inputs are gathered from elsewhere (potentially asynchronously), it looks like htmy wants to make it easy to define hierarchies of components. Instead of `is_admin()`, imagine a dashboard whose layout is stored in a database, supporting configurable charts of various flavors. The heterogeneity of the data supporting different types of charts makes it hard to efficiently pull data in a single SQL query (equivalently, any reasonable database model), so somewhere in your code you're pulling a bunch of data asynchronously, and somewhere else you're rendering it. The question, still, is "where?"
Going back to the idea of htmy defining hierarchies of components, imagine how annoying it would be to have to manually grab all the data for a "reporting page" component only to feed it straight back into the renderer -- either having to duplicate the hierarchial structure when feeding data into the renderer (a technique some UI libraries employ, though I don't like it) -- or having to come up with a method for flattening that hierarchy when instantiating the component (another technique some UI libraries employ, one I like more for small projects and less for large ones).
They solve that (to the extent that you think it needs solving) by bundling all that background logic into the components themselves. Did they really need to implement that recursively instead of just walking the hierarchy, gathering the data up-front, and populating it? Eh. The code winds up being similar either way, and either way it definitely forces async back into the middle of HTML rendering.
Mind you, that tends to either make some applications hard to build or to cause the framework to explode in complexity over time as people need new and new ways to say "yes, re-render this thing; no, re-render that other thing, but don't grab its data, ...." There's enough less particularly annoying code involved though that fat, smart components are a natural place for people to gravitate.
Unrelated to htmy completely, a technique I like from time to time even for problems which don't need async per se (and I'm usually using lower-level languages, so the implementation is some sort of more manual continuation pattern, but all those things are basically async, so I won't dwell on the details) is explicitly designing pausable/restartable structures for long-running computations. It's about as easy to write as purely iterative code, and you can run the result as purely iterative with no runtime overhead, so the downsides are low. It opens the door though to easily tuning how long you defer invariant maintenance (too infrequent and your algorithm devolves to the slow thing it's replacing, too frequent and the overhead isn't worth it), easily checkpointing a computation, adding other custom runners for an algorithm (like animating its progress), .... I can absolutely see a use-case for wanting to visualize each step of an HTML rendering, or log OS network counters after each step, and so on. Python's async isn't really the right tool for the job for that (it's hard to modify the runtime to support them without building quite a lot of nonsense from scratch), but async in the abstract isn't bad at all per se.
Oh it's server side "rendering"?
I was looking for something like this a few weeks ago. I typically use Django and hate the template engines limitations. I needed to make some reusable components and the best option available was switching to jinja to get their macro support, bleh.
This reminds me of the best part of Flutter UI composition, but in a language I always return to.
Have you done any benchmarking? I don't even know what the comparison would be.
You might want to look at django-cotton for components
Looks similar to a framework I've been using for some personal sites reflex.dev, pretty cool when would you recommend using this over that?
Is there a comparison or guide to choosing python frameworks? Every few weeks there's a new one posted here
In the real world, for web things, people use django or fastapi. I'd suggest picking a project with lots of stackoverflow questions and poking around their docs to see which makes you the most comfortable. Personally I tend to favor litestar these days since it has good docs and issues don't sit around for years waiting on one dude to merge prs (fastapi) and it's a lot nicer than django (and I hate django docs).
Flask/quart are painful to work with due to horrible documentation in my experience, but they're popular too. Quart is just an async rewrite of flask by the same owners.
Litestar has a half baked comparison chart here: https://docs.litestar.dev/latest/
I think the “rule of thumb” is that none of them are better than using HTMX with templates. HTMX obviously having some limits in terms of security and complex REBAC.
Or Unpoly. I've been working with it for a month now and it's a real pity such a robust library it gets so little attention.
Looks great. Anyone using this in production?
Would love to see some benchmarks for all these libraries that compare them to Jinja2.
How does this compare with FastHTML?