Caching with turbo streams?


So, i have a page that is updated via turbo streams. So, a click is linked and page is updated no problem there.

This just came in my mind, is it possible to cache the views in such a way that the turbo stream does not update the parts of the page unless it was changed(updated)?


I’m not sure I understand. Can you provide a “for example”?

If you have to fetch (or stream) the frame contents to determine if its different, the only reasons I can think of to not replace the DOM with it would be if it contained inputs or focus.

You could stream to a different (hidden or outside of body) frame and code whatever reasoning you required to move to the visible DOM

Sorry, definitely. Let me try to explain this, look at this

Whenever a conversation(left hand side) is clicked, i submit a turbo stream request to replace the inbox and the right hand side of the page.

Now, when the inbox is replaced, the right hand side itself is an eager-loaded turbo frame

  class="hidden md:flex w-4/12 ml-2 p-1 flex-col items-start mt-4 overflow-x-hidden overflow-y-auto relative">
  <% if @conversation.present? %>
    <%= turbo_frame_tag dom_id(@conversation, :participants),
                        src: conversation_participants_path(@conversation),
                        class: 'w-full flex flex-col justify-center',
                        data: { conversations__inbox_target: "participants"} %>
  <% end %>

As you can see in the video, the skeleton loaders are reloading everytime and it makes sense because each time the conversation was clicked, it submits a turbo stream request to update the page.

I was wondering if it’s possible to somewhat allow them to be cached such that the skeleton loaders don’t load after the initial load. I thought about disabling the active conversation for sometime, but i was wondering if it was possible with streams. Thanks

Could you explain this a bit more, if possible. Thanks.

If you clicked the same link on the left side, could the content on the right ever change from the backend and be an issue with caching?

what do you mean, sorry i did not understand.

Let me step back. From a high level, does your layout look something this?

  <aside id="conversation_menu">
    <a href="converstion/1" data-turbo-frame="conversation">Conversation 1</a>

  <turbo-frame id="conversation"></turbo-frame>

<!-- conversation response -->
<turbo-frame id="conversation">
  <div id="inbox"></div>
    <turbo-frame id="participants" src="conversation/123/participants">
      <div>[Skeleton Loader...]</div>

<!-- participants response -->
<turbo-frame id="participants" src="conversation/123/participants">
  1. Conversation click updates inbox turbo-frame
  2. The turbo-frame response includes HTML for a participants “skeleton” and a participants turbo-frame
  3. Participants are loaded via the 2nd turbo-frame request

is this correct?

You are correct. But it’s all turbo_stream.replace calls, not frames. conversaitions/show.turbo_stream.erb

<%= turbo_stream.replace "conversation-inbox", class: "w-full flex" do %>
  <%= turbo_stream_from @conversation %>
    id="conversation-inbox" class="w-full flex">
<% end %>

<%= turbo_stream.replace dom_id(@conversation) do %>
  <%= render @conversation, viewed_conversation: @conversation, business: @business %>
<% end %>

I recommend using turbo-frame over turbo-stream for this.

  1. When not altering state on the backend, GET request is recommended
  2. You can speed up GET requests with eTags.

This would speed up the responsiveness of the page. I might also consider one these options:

  • delay showing the participant skeleton a few hundred milliseconds. If the participant html loads before the skeleton loads, then you never see the skeleton.
  • consider removing the participant skeleton for this area. I’ve found that in some areas, the skeleton technique does not always turn out and I remove it.
1 Like

@tleish sorry for bothering again. But, i’ve worked on what you proposed and it already got me far where i want to be.

One thing is. Do you know how to update urls when navigating towards a frame?. I’ve modefied the links to target the specific frame. They UI is updated successfully, but the url is not. When i click on a conversation on the left side the url is not updated successfully. But, the rendered frame from the server has the correct src.

What i want is when i click the link

 <aside id="conversation_menu">
    <a href="converstion/1" data-turbo-frame="conversation">Conversation 1</a>

it to update thr url. I’ve swept through the various PRs addressing this but could not get it to work.


I assume you mean the Page URL, and not the Frame URL? The team just added support for this in the latest turbo v7.1.0.

See: Promoting a Frame Navigation to a Page Visit

1 Like