In my htmx project, the best I could pull off was:
1) every server build has a unique version ID
2) the version ID is embedded in the page on the first page load
3) on every htmx request (it can be done with a bit of HTMX configuration) the embedded version ID is sent to the server as a special HTTP header
4) a middleware on the server always compares the version IDs, and if they don't match, sends back a special "reload" HTTP response header
5) on each response, htmx checks if the reload header is present, and if the user navigates to a logically different page (which is usually part of SPA), then a full page reload happens (I have a few heuristics to tell if it's a logically different page or just a component update on a page) - to avoid losing state when the user is editing something (i.e. not just navigating)
6) all assets are versioned on full page render, so the full page reload triggers CSS/JS update
And it works on all pages automatically with 100 lines of additional JS on top of htmx.
Differences from LiveView:
1) each HTMX request still has all the overhead of auth checks
2) UI updates are not immediate, but only when the user attempts to navigate in the SPA (can be problematic if partials from different server builds are mixed on the page before a full reload, and they're not compatible)
3) UI updates trigger full page reloads which are noticeable by the user but generally it's OK because releases don't happen very often and critical user input isn't lost
Are assets versioned by URL (/path/to/foo-1234abcd.js or /1234abcd/path/to/foo.js) or are they updated in-place (/path/to/foo.js, but now containing 'const version="1234abcd";')?
If the first one, if you don't do it already, your reload header could act like a "preload" header ("Htmx-Preload-Root: 1234abcd") and tell the client which assets to start pulling even before a logical navigation click, so that they're hot in the cache when they eventually do that navigation.
Nice idea! The assets are versioned by URL. Indeed, if it's just a component update (not navigation), we can't fully reload yet, but we already know at that point that we can start pulling the new assets.
1) every server build has a unique version ID
2) the version ID is embedded in the page on the first page load
3) on every htmx request (it can be done with a bit of HTMX configuration) the embedded version ID is sent to the server as a special HTTP header
4) a middleware on the server always compares the version IDs, and if they don't match, sends back a special "reload" HTTP response header
5) on each response, htmx checks if the reload header is present, and if the user navigates to a logically different page (which is usually part of SPA), then a full page reload happens (I have a few heuristics to tell if it's a logically different page or just a component update on a page) - to avoid losing state when the user is editing something (i.e. not just navigating)
6) all assets are versioned on full page render, so the full page reload triggers CSS/JS update
And it works on all pages automatically with 100 lines of additional JS on top of htmx.
Differences from LiveView:
1) each HTMX request still has all the overhead of auth checks
2) UI updates are not immediate, but only when the user attempts to navigate in the SPA (can be problematic if partials from different server builds are mixed on the page before a full reload, and they're not compatible)
3) UI updates trigger full page reloads which are noticeable by the user but generally it's OK because releases don't happen very often and critical user input isn't lost