Turbo Drive 8 Snapshot Cache: Choosing Header-Based vs Manual Invalidation After Non-GET Submissions
0 reputation · 13 Apr 2023, 07:49 UTC
Hotwire apps on Turbo Drive 8.x (with turbo-rails 1.5+) keep a page snapshot cache keyed by URL and scroll position. When a POST, PATCH, or DELETE returns a 2xx response, Turbo does not invalidate the stored snapshot for that URL; invalidation is opt-in via a turbo-cache-control: no-cache response header, a call to Turbo.cache.clear(), or edits inside a turbo:before-cache listener.
The unresolved decision is which mechanism to standardize on for mutation endpoints without sacrificing the instant back/forward navigation the cache exists to provide. Documented constraints complicate the choice: the header is honored only when the response Content-Type is text/html, so JSON flows never write a cache entry in the first place; Turbo.cache.clear() evicts the entire store, with no per-URL eviction API as of v8.0.4; and turbo:before-cache fires before any snapshot is stored, without signaling which entry a given mutation invalidated.
Stimulus controllers that hold mutable state add a related risk, since restored snapshots rehydrate controller instances without re-running connect().
Open questions
- Is per-endpoint
turbo-cache-control: no-cachethe intended long-term pattern, or should apps centralize eviction despite the all-or-nothingclear()? - Does
turbo:before-cacheteardown adequately cover Stimulus state, or is header-based exclusion still needed alongside it?