DEV Community

Cover image for Lazy Loading With Turbo [Rails]
Michael Roudnitski
Michael Roudnitski

Posted on • Updated on

Lazy Loading With Turbo [Rails]

The speed of a single-page web application without having to write any JavaScript.


Turbo allows you to add SPA functionality to your web apps. It comes with three components,

  1. Turbo Drive
  2. Turbo Frames
  3. Turbo Streams

To add lazy loading to our page, we'll be using Turbo Frames. You can install Turbo directly into your Rails application.

Why Use Lazy Loading

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.

What Is 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 where they lazy load their videos.
Screen Shot 2021-04-26 at 3.54.01 PM

They're showing you skeleton loading indicators while you wait to see if Mr. Beast bought a country yet.

Using Turbo Frames To Lazy Load

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_tag "blog_posts" %>
  <h2>Done loading! Here are my blog posts.</h2>
  <%= @blog_posts.each do |post| %>
    <%= post.title %>
    <%= post.description %>
  <% end %>
<% end %>
Enter fullscreen mode Exit fullscreen mode

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!
Enter fullscreen mode Exit fullscreen mode

And of course, don't forget to add a GET route to your new action in routes.rb.

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 src= attribute.

<%= turbo_frame_tag "blog_posts", src: blog_posts_path do %>
Enter fullscreen mode Exit fullscreen mode

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_tag "blog_posts" %>
<% end %>
Enter fullscreen mode Exit fullscreen mode

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).


Turbo is super powerful and it can help you modernize your Rails app without writing JavaScript. And of course, Turbo doesn't have to be used with Rails! Everything I wrote about can even be applied to a JavaScript app if you're feeling especially crazy 😜.

For more info, check out the official handbook here.

Top comments (2)

joshrburks profile image
Josh Burks

For consistency, you might want to use turbo_frame_tag in your blog_posts.html.erb file as well.

michaeldrrc profile image

Nice bro