How to enable or disable Prefetching in Ruby on Rails and Turbo
Before we dive into the code, let's understand what we're dealing with. Turbo (part of the Hotwire stack) includes a feature called prefetching that automatically loads linked pages before a user clicks on them. When a user hovers over a link, Turbo starts downloading the linked page in the background, making the navigation feel lightning-fast when they actually click.
While this is generally awesome for user experience, it can cause problems in certain scenarios:
- Pages with heavy data processing
- Admin sections with complex reports
- Pages that trigger expensive database queries
- Resource-intensive analytics dashboards
Prefetching these types of pages can unnecessarily strain your server and slow down the current page experience.
Understanding the data-turbo-prefetch attribute
Turbo provides a simple way to control prefetching behavior using the data-turbo-prefetch
attribute. This attribute can be applied to:
- Individual links
- Container elements (which affect all links inside them)
- The entire document
The attribute accepts two values:
"true"
- Explicitly enables prefetching"false"
- Explicitly disables prefetching
If the attribute is not specified, Turbo follows its default behavior (which is to prefetch links on hover).
Implementing selective prefetching in your Rails app
Let's look at a practical example. Imagine you have a navigation component with some links that should be prefetched (like dashboard and user management) and others that shouldn't (like heavy analytics reports).
Here's how you might structure this in your Rails view:
<nav class="navigation">
<aside data-turbo-prefetch="true">
<%= link_to "Dashboard", dashboard_path %>
<%= link_to "Users", admin_users_path %>
</aside>
<main data-turbo-prefetch="false">
<%= link_to "Heavy Analytics and Reportings", analytics_repots_path %>
<%= link_to "Heavy Logs", logs_path %>
</main>
</nav>
In this example:
- Links inside the
<aside>
element will be prefetched when hovered - Links inside the
<main>
element will not be prefetched, preventing unnecessary server load
Disabling prefetching for individual links
Sometimes you might want more granular control. You can apply the attribute directly to individual links:
<div class="quick-links">
<%= link_to "User Profile", profile_path %>
<%= link_to "Settings", settings_path %>
<!-- This heavy report won't be prefetched -->
<%= link_to "Generate Full Audit Report", audit_report_path, data: { turbo_prefetch: false } %>
</div>
Performance considerations and best practices
When implementing selective prefetching, keep these tips in mind:
- Be strategic: Disable prefetching only where it makes sense - pages with heavy database queries, complex calculations, or large payloads.
- Monitor performance: Use tools like Scout APM, New Relic, or Skylight to identify which pages are causing the most load.
- Consider user patterns: If analytics show users rarely navigate to certain sections, those are good candidates for disabling prefetching.
- Test the impact: Measure the performance difference with and without prefetching to ensure your changes are beneficial.
- Use caching where appropriate: For some heavy pages, implementing proper caching might be better than disabling prefetching.
Summary
Turbo's prefetching is a powerful feature that can significantly improve the perceived performance of your Rails application. However, it's important to use it judiciously, especially for resource-intensive pages.
By using the data-turbo-prefetch
attribute strategically, you can create a balanced approach that gives users a fast experience while preventing unnecessary server load. Remember to:
- Enable prefetching for frequently accessed, lightweight pages
- Disable it for resource-intensive sections
- Consider user patterns and actual performance metrics when making these decisions
With these techniques, you'll be able to harness the power of Turbo while keeping your application running smoothly.