Turbo allows you to send HTML over Websockets. It comes with three components,
- Turbo Drive
- Turbo Frames
- Turbo Streams
To add lazy loading to our page, we'll be using Turbo Frames. You can install Turbo directly into your Rails application.
Let's say we have a blog and when a reader visits our blog, we want it to feel ⚡️ lightning quick; because we want them to come back someday. One way of accomplishing this is using a very common technique called lazy-loading.
Our server can send out a light weight HTML page with loading indicators in place of our blog posts. Only after this light weight page fully loads, we can request our blog posts from the server.
You can see examples of lazy loading everywhere in the wild, here's an example from https://youtube.com where they lazy load their videos.
They're showing you skeleton loading indicators while you wait to see if Mr. Beast bought a country yet.
So how can we use Turbo to lazy load our blog posts? It's really simple! We just need to add an action to our controller so we can separate blog post loading from our traditional index action.
Let's start with our erb templates:
# index.html.erb <h1>Hello World! Check out my blog posts below 👇</h1> <%= turbo_frame_tag "blog_posts", src: blog_posts_path do %> <h2>Hold on a sec while I fetch my blog posts...</h2> <%# once blog_posts_path responds, it will replace everything inside this turbo frame tag with blog_posts.html.erb %> <% end %> # blog_posts.html.erb <turbo-frame id="blog_posts"> <h2>Done loading! Here are my blog posts.</h2> <%= @blog_posts.each do |post| %> <%= post.title %> <%= post.description %> <% end %> </turbo-frame>
And now in our controller:
# GET /blog def index; end # GET /blog_posts def blog_posts @blog_posts = BlogPost.all render layout: false # Don't forget this optimization! end
And of course, don't forget to add a GET route to your new action in
This is all you need to do with Turbo Frames to accomplish lazy loading! We just had to add 1 action and 1 view.
Let's go through it: when a user lands on our
index page, we send them a very small
index.html.erb file that lets them know our blog posts are loading. Once this page is loaded in the browser, Turbo will see we have a turbo frame tag on the page and it will notice our
<%= turbo_frame_tag "blog_posts", src: blog_posts_path do %>
Turbo will then launch a request to
blog_posts_path and when a response with a matching turbo frame tag comes in,
# notice the id matches our turbo frame tag in index.html.erb <turbo-frame id="blog_posts"> ... </turbo-frame>
Turbo will work it's magic and replace our loading indicator with our blog posts!
As of Turbo 7 you can now add the
loading="lazy" attribute to your turbo frame, which will only load your frame once it becomes visible to the user (when they scroll down for example).
For more info, check out the official handbook here.