Lazy Loading With Turbo [Rails]
Tags: rails, turbo, tutorial, webdev
Published: 2021-04-26 21:30:09

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

# Overview
[Turbo](https://turbo.hotwire.dev) allows you to add SPA functionality to your web apps. It comes with three components,
1. Turbo Drive
1. **Turbo Frames**
1. Turbo Streams

To add lazy loading to our page, we'll be using Turbo Frames. You can [install Turbo](https://turbo.hotwire.dev/handbook/installing#in-a-ruby-on-rails-application) 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 https://youtube.com where they lazy load their videos.
![Screen Shot 2021-04-26 at 3.54.01 PM](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pzqyh19iood1rq1iu76z.png)

They're showing you [skeleton loading indicators](https://tailwindcss.com/docs/animation#pulse) 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:
```erb
# 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 %>
```

And now in our controller:
```Ruby
# 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 `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.
```erb
<%= 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,
```erb
# notice the id matches our turbo frame tag in index.html.erb
<%= turbo_frame_tag "blog_posts" %>
...
<% end %>
``` 
Turbo will work it's magic and replace our loading indicator with our blog posts!

# Tip
As of [Turbo 7](https://world.hey.com/hotwired/turbo-7-0dd7a27f) 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).

# Conclusion
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](https://turbo.hotwire.dev/handbook/frames#lazily-loading-frames).