htmx icon indicating copy to clipboard operation
htmx copied to clipboard

Proposal(?): adding stale-while-revalidate caching pattern?

Open frederikhors opened this issue 2 years ago • 14 comments

I just found out htmx and I would like to try it as soon as possible.

I also agree that SPAs are a real fatigue.

I'm using SPAs mainly for two features:

  1. I'm obsessed with perceived speed of rendering between pages transition. Especially with list > details workflows I'm using the stale-while-revalidate pattern a lot to increase the perceived speed of data fetching (using graphql normalized cache packages like Apollo and urql).

  2. I'm really productive with code like frontend calculation only, example: the sum of invoices rows; I mean, list of something to calculate on frontend only without backend calls at all.

I searched a lot on Google and here on GitHub about htmx and stale-while-revalidate but nothing showed up.

I was thinking about using service worker for this but found nothing ready.

Can you help me find a way?

What do you think?

UPDATE:

I better explained what I need here: https://github.com/bigskysoftware/htmx/discussions/1706#discussioncomment-6807043.

frederikhors avatar May 17 '23 08:05 frederikhors

There is the preload extension which could help with the list > details workflows that you mentioned: https://htmx.org/extensions/preload/

thomaseizinger avatar May 31 '23 08:05 thomaseizinger

2. I'm really productive with code like frontend calculation only, example: the sum of invoices rows; I mean, list of something to calculate on frontend only without backend calls at all.

I'd say the way to think about this is that the webserver serving your HTML is your frontend. The sum of invoice rows is not going to change without an invoice being deleted or added which needs a server-roundtrip anyway. That roundtrip sends you back the new HTML to render.

In a way, you need 0 backend calls and avoid writing an API to start with because your server can just render HTML based on what is in its database.

thomaseizinger avatar May 31 '23 08:05 thomaseizinger

I had a similar idea of an "hx-local" or "hx-template" attribute: it acts like hx-get, except instead of a url it takes an element reference, and the "ajax response" instead comes from the innerHTML of the element. This would work well with

The stale data in the

danielkeller avatar Aug 10 '23 08:08 danielkeller

Isn't this already possible by adding an hx-get to a regular div?

The content of the div will be immediately rendered, the AJAX request runs in the background and updates the UI as soon as it is finished.

On the first page load, this isn't very useful because the UI is already coming from the server (assuming the DB query isn't super expensive).

But if the HTML is served from the local browser cache (if the user presses back for example?), then I think this would trigger a new AJAX request and update the data.

However, I do think the whole SWR pattern isn't as useful as for SPAs because you typically just get the new UI from the server anyway.

thomaseizinger avatar Aug 20 '23 07:08 thomaseizinger

Do we have an example? @thomaseizinger

frederikhors avatar Aug 20 '23 10:08 frederikhors

It seems to me that something like this would be best done as part of a broader effort to build some sort of pwa integration/extension into HTMX - there's a lot of useful caching strategies aside from stale-while-revalidate.

There's already Google's Workbox library for implementing caching strategies (and much more). But it's somewhat large and also seemingly abandoned. So, there's probably an opportunity to create some sort of htmx-workbox extension that could implement select features of workbox - be it by directly porting code, or re-writing as-necessary.

I'd be open to contributing to this in a few month's time, if others are interested in collaborating.

nickchomey avatar Aug 20 '23 15:08 nickchomey

Do we have an example? @thomaseizinger

Of what exactly? Adding hx-get to a div? I'd say the reference explains that pretty well: https://htmx.org/attributes/hx-get/

This blog post discusses more ideas of what you can build with that: https://anto.pt/articles/rust-server-components

thomaseizinger avatar Aug 21 '23 09:08 thomaseizinger

I better explained what I need here: https://github.com/bigskysoftware/htmx/discussions/1706#discussioncomment-6807043.

Isn't this already possible by adding an hx-get to a regular div?

The content of the div will be immediately rendered, the AJAX request runs in the background and updates the UI as soon as it is finished.

Maybe this can work with service-workers?

frederikhors avatar Aug 23 '23 21:08 frederikhors

I better explained what I need here: #1706 (reply in thread).

I see. The following could be interesting, I think it is possible to implement as an extension:

  • Set up a cache and register each response to a GET request based on the htmx::afterRequest event. You might want to inspect the Cache-Control header to see if caching is allowed.
  • For every htmx::beforeSend event, look in the cache and swap in the last item you find, perhaps together with a small indicator, telling the user that the data is being updated.

The above implies that you are already offloading certain components in your HTML page using hx-get. You'd probably also want to make the above behaviour conditional based on same attribute on an hx-get node.

I think that HTMX will still run the AJAX request in the background and perform the swap with the actual, fresh data.

cc @1cg would know more about the inner workings.

thomaseizinger avatar Aug 24 '23 13:08 thomaseizinger

@thomaseizinger It would be amazing to have a repl online for this! :smile:

frederikhors avatar Aug 24 '23 18:08 frederikhors

I usually send the most recent data in the first full page response and only then use Ajax calls to refresh. I don't think it's cool to render any page and then have 20 requests properly loading the site. This is more of a UX fail than the other way round.

Seeing old data and suddenly have it changed/replaced is also a bit strange. This would drive me mad as user.

andryyy avatar Aug 24 '23 18:08 andryyy

I usually send the most recent data in the first full page response and only then use Ajax calls to refresh. I don't think it's cool to render any page and then have 20 requests properly loading the site. This is more of a UX fail than the other way round.

Seeing old data and suddenly have it changed/replaced is also a bit strange. This would drive me mad as user.

Definitely for the initial load yes. I can see some value in refreshing parts of the page if you've for example restored a page from a history entry or loaded it from the cache in general.

I do agree that it doesn't fit that well into HTMX and it might introduce weird, inconsistent states that make you do a full page reload anyway.

SWR is nice for SPAs that differentiate between the shell and actual data being displayed. That isn't really the case in HTMX because you can just load the full page with fresh data using little bandwidth.

@thomaseizinger It would be amazing to have a repl online for this! :smile:

I don't have a use for it at the moment but the above should give you enough starting points to attempt an implementation yourself :)

Please share if you have something, I'd be curious how the UX works out.

thomaseizinger avatar Aug 25 '23 06:08 thomaseizinger

@thomaseizinger do you have news for this eventually?

frederikhors avatar Jun 20 '24 19:06 frederikhors

@thomaseizinger do you have news for this eventually?

No, I have not been using HTMX for anything lately.

thomaseizinger avatar Jun 21 '24 12:06 thomaseizinger