A 500-800ms speed boost you didn't know you had!
Modern web users are impatient, and who can blame them? We've all clicked a link, waited a second, and immediately questioned our life choices. But what if we could make every link in your Rails app feel instant without adding a single spinner or loading bar?
Thanks to Turbo v8, we can. And the secret? Prefetching links on hover.
Let's dive into what this means for you as a Rails developer using good old link_to
, and how you can make the most of it, or disable it where needed.
Turbo now prefetches pages in the background as soon as the user hovers over a link for more than 100ms. That means the content starts loading before they even click. On average, this gives you a 500-800ms head start. And your app feels blazing fast.
Let's say you're building a learning dashboard in Rails, where users can quickly jump between "Today's Lesson," "Progress," and "Leaderboard." Here's how you'd typically render those links:
<ul class="sidebar-nav"> <li><%= link_to "Today's Lesson", todays_lesson_path %></li> <li><%= link_to "Progress", progress_path %></li> <li><%= link_to "Leaderboard", leaderboard_path %></li> </ul>
With Turbo v8 installed (included in Rails 7+ apps using Hotwire), each of these links will prefetch their destination page as soon as the user hovers. No extra markup. No JavaScript needed. So when the user finally clicks "Leaderboard," it loads like lightning ⚡.
Because most latency isn't the page load, it's the network roundtrip. Turbo removes that by starting the request early, while the user is still thinking. This works especially well for:
Some pages don't benefit from this, or even suffer from it. Say you have a link that triggers expensive database queries or a Data Export that takes a while to prepare. No point preloading it unless the user clicks.
Let's imagine a Data Export page that takes a while to prepare. You can disable prefetching for just that link:
<%= link_to "Data Export", export_path, data: { turbo_prefetch: false } %>
Turbo will skip prefetching this one while keeping the rest of the app fast.
Imagine this layout:
<div class="admin-dashboard"> <aside data-turbo-prefetch="true"> <%= link_to "Overview", admin_overview_path %> <%= link_to "Users", admin_users_path %> </aside> <main data-turbo-prefetch="false"> <%= link_to "Heavy Report", analytics_report_path %> <%= link_to "Export Logs", logs_path %> </main> </div>
Here's what happens:
<aside>
are prefetched.<main>
are not prefetched.This gives you precise control, letting fast, frequent links get the speed boost, while leaving heavier ones alone.
Want to be respectful to users with limited data? You can disable prefetching dynamically using JavaScript:
document.addEventListener("turbo:before-prefetch", (event) => { if (navigator.connection?.saveData || isSlowConnection()) { event.preventDefault() } }); function isSlowConnection() { return ["slow-2g", "2g"].includes(navigator.connection?.effectiveType) }
This ensures you're not fetching pages the user may never click, especially on metered or slow connections.
link_to
<meta name="turbo-prefetch" content="false">
data: { turbo_prefetch: false }
turbo:before-prefetch
to cancel based on network conditionsPrefetching might sound like a small optimization, but it's one of those feel improvements that makes your app seem much faster than it really is. The best part? You don't have to change your app. You're already writing link_to
. Turbo just makes it smarter.
Want more modern Rails tricks like this? Check out RubyCademy where we turn everyday Ruby, Rails, and Hotwire into your superpower.
Voilà!
RubyCademy ©