Prefetching in Inertia

November 13th, 2024 • 4 minutes read time

Want to improve the perceived performance of your applications? Prefetching is a great first step. Here's how it works in Inertia v2.

Users who navigate your application mainly do so through pages or click buttons. Prefetching allows you to load data required for the next page or action behind the scenes before they see the data.

Usually, this is done on a mouseover (hover) event in JavaScript.

Because a user is likely to hover over a link before they click to see the next page, prefetching as they hover means that when they do click, the data has already been fetched from the backend and can instantly be displayed.

Let's cover how prefetching works in Inertia, both with the Link component and programmatic prefetching.

Imagine you have a route in your application that loads a list of users. Here's what the controller rendering the Inertia response may look like.

return Inertia::render('Users', [
    'users' => User::paginate(5)
]);

Assuming this route is at /users, here's what a link in your navigation may look like:

<Link :href="route('users')">
    Users
</Link>

When a user navigates to /users without prefetching, the users prop data will only be loaded once they land on the page.

Here's the adjusted Link with prefetching enabled:

<Link
    :href="route('users')"
    prefetch
>
    Users
</Link>

That's it. By default, when a user hovers over this link, the prop data for /users (in this case, just users) will be loaded via an HTTP request and cached in the background.

When they eventually decide to click the link, the data will already be there, and they'll see an instant page load!

Here's a video of what this looks like with the network tab open:

blog/OyNOVDmdMi45a19bdJKYNucWFiCTb9eVxaSq2EAb.gif

Because the data needs to be cached across requests, you may need to adjust the cache duration based on how fresh you need the data to be.

The default cache duration in our example above is 30 seconds at the time of writing. Here's how to adjust the duration:

<Link
    :href="route('users')"
    prefetch
    cache-for="1m"
>
    Users
</Link>

You can use any similar values for this (e.g. 5m, 45s, etc), or you can specify the duration in milliseconds:

<Link
    :href="route('users')"
    prefetch
    :cache-for="10000" <!-- 10 seconds -->
>
    Users
</Link>

Prefetching in Inertia also supports the Stale while revalidate pattern, allowing you to control when data is considered fresh or stale and flush the cache accordingly. You'll find information and examples of this in the Inertia documentation.

We know by default, hovering over a link triggers a prefetch.

You're able to customise this by passing either a string or array into the prefetch prop. Here's an example of triggering this on mount:

<Link
    :href="route('users')"
    prefetch="mount"
>
    Users
</Link>

Triggering prefetching on mount is a good way to prefetch data that you know a user will visit. This could be a popular or critical page that you know performs slowly. Prefetching, as soon as they hit the page, gives the data time to load before eventually navigating.

Be careful with prefetching too much though. Adjust your strategy so you're not prefetching everything, or you'll return to slower performance.

You're able to choose multiple events to prefetch with. Here's an example:

<Link
    :href="route('users')"
    :prefetch="['mount', 'hover']"
    cache-for="5m"
>
    Users
</Link>

Here, we're prefetching on mount and hover. Why?

You may want to prefetch when the page is mounted, but this data is cached and will eventually invalidate. Suppose the cache does invalidate (after 5 minutes in this example) before the user navigates to the prefetched page. In that case, you can prefetch again on hover to prefetch again.

Prefetching isn't just reserved for the Link component; it also works directly with Inertia's router.

Here's a quick example:

router.prefetch(
    '/users',
    { method: 'get' },
    { cacheFor: '5m' },
)

This programmatic prefetch is identical to our Link prefetch but allows you to control this directly with JavaScript.

A use-case for this is pagination, infinite scrolling, or any kind of 'load more' functionality, as you can anticipate the next batch of data being loaded and prefetch it. We cover this in the New in Inertia course by building a full working example!

Because prefetched data is cached, you may need to bust the cache at some point, or you'll end up with stale data.

Imagine this scenario:

  1. You display a list of items
  2. Your user performs an action to modify this list of items
  3. The data gets prefetched (either by a hover or another event)
  4. The cache returns the stale data

Not ideal. Here's how you flush the prefetched cache with Inertia prefetching:

router.flush(
    '/users',
    { method: 'get' },
)

Remember that data is cached based on the exact request, so if you included any additional data when prefetching, you'd need to match it up exactly.

For example, if you prefetched with a Link like this:

<Link
    :href="route('users')"
    cache-for="5m"
    :data="{ page: 1 }"
>
    Users
</Link>

Then you'd need to include the page when you flush:

router.flush(
    '/users',
    { method: 'get', data: { page: 1 } },
)

So, that's prefetching in Inertia! A great place to start for most applications is prefetching the most common (or slow) pages through any Links. However, programmatic prefetching works well for data loaded via a button or other action.

You can learn about everything new in Inertia with our New in Inertia course, including more practical prefetching examples.

If you found this article helpful, you'll love our practical screencasts.
Author
Alex Garrett-Smith
Share :

Comments

No comments, yet. Be the first!