Closed BenCh94 closed 6 months ago
Thank you for opening this issue.
Are your <a>
elements rendered with [data-turbo-stream]
? If they are, they should be ignored by the Link Prefetcher.
If you're able, could you modify the script shared below to reproduce your behavior?
@seanpdoyle adding [data-turbo-stream]
to the fixed this issue, thanks for the quick reply
I have found this issue because I ran into the same issue. An endpoint may respond with a turbo stream and the turbo stream was being executed on prefetching.
Adding data-turbo-stream
indeed works but I am left wondering what is preventing Turbo from ignoring the prefetch result if it comes back as a turbo stream response to avoid having to remember to specify the attribute?
I am thinking that the following 2 statements are true based on the documentation and feature intent:
Putting this to together it seems clear that prefetch should always ignore stream action Content-Type
response.
Are there any reasons for not implementing this change to remove a non obvious prefetch pitfall?
I had a quick debug session to see why this is happening and the short answer is:
StreamObserver#start
listens for before-fetch-response
and renders and stream messages into the body to get them to execute. It's doesn't discriminate and does this for all fetch requests. As far as I could tell, it's the only Turbo internal code listening to this event.LinkPrefetchObserver#tryToPrefetchRequest
constructs a regular prefetch request but saves the response without acting on it. However, that happens after the callbacks fire, i.e. too late.There's no way for the StreamObserver
to differentiate fetches that are regular vs those originating from a prefetch.
The easiest way to fix it would be add a property for FetchRequest
indicating if it is a prefetch request and then modify behaviour based on it. However that would couple StreamObserver
and probably some other classes to the logic of prefetching, making it more expensive to maintain long term.
It would be better if handling of a stream response was decoupled from fetching, same as it is for regular HTML responses.
HTML response gets fetched and is later used by the other code. But a stream response fetching is intercepted and then the response is acted on during the fetching process.
This is fundamentally at opposition to the concept of prefetching. More importantly, it will also be a problem for any future feature that needs request fetching and response handling separated in any way.
I am not yet sure on how the refactoring should look, that would need to be discovered in code. I am interested to try that but before putting effort into it, I'd like to know if this work would be even welcomed by the maintainers?
We have a filtering page with several filter dropdowns, each dropdown contains a list of aggregations from our OpenSearch response and renders a link_to tag.
these link_to tags sit inside a turbo_frame and the action responds with a turbo_stream that updates results and the filters on the page.
In the latest release of turbo-rails these links are rendering the turbo stream response on hover before the user clicks anything. This seems to be a result of the pre-fetch links enabled by default in Turbo 8.
We're aware of the ability to disable the prefetch functionality on a per-element basis but is this the expected default behavior for a link_to that responds with a turbo_stream, should we be converting any link_to tags to button_to or some other tag to avoid this behavior in the future?