I ran into an issue with an API I am using that in its terms forbid any kind of server side caching, but allowed client side caching.
I ended up doing a simple trick in my Rails app:
<!-- index.html.erb -->
<turbo-frame id="api-results" src="/api_results"/>
<!-- api_results.html.erb -->
<turbo-frame id="api-results">
<div data-controller="cache" data-cache-duration-value="60">
<!-- ... all the results -->
</turbo-frame>
And two reusable Stimulus controllers:
// cache_controller.js
import { Controller } from "stimulus"
export default class extends Controller {
static values = { duration: Number }
connect() {
var parent = this.element.parentNode
if (parent.src) {
parent.dataset.controller = "cached"
parent.dataset.cachedFetchAfterValue = Date.now() + (this.durationValue * 1000)
parent.dataset.cachedSrcValue = parent.src
parent.src = ''
}
}
}
// cached_controller.js
import { Controller } from "stimulus"
export default class extends Controller {
static values = { fetchAfter: Number, src: String }
connect() {
if (Date.now() >= this.fetchAfterValue) {
this.element.src = this.srcValue;
}
}
}
Whenever content is loaded that I want to cache client side, I add the prefix div, which, when connected, wipes the src
of the parent turbo-frame, and adds a controller, that, when connected, checks if it needs to re-add it after x seconds.