Faster navigations with automatic route prefetching

Next.js uses file-system-based routing: pages live as files in the ./pages/ directory, and no manual route setup is needed. Navigation between those pages is normally handled with the <Link> component, which works like a standard <a> element but adds one optimization.

When a page with links loads, Next.js automatically prefetches the JavaScript required to render the linked pages. By the time a user clicks a link, the component behind it has often already been fetched, making the navigation feel instant. This behavior applies to any <Link> that is visible in the viewport.

Prefetching in the network tab

You can verify this in Chrome DevTools. Load a page that contains a <Link> to another route, open the Network tab, and check Disable cache. After reloading, the target page's JavaScript bundle appears in the list of downloaded files alongside the current page.

Conditions and limits of automatic prefetching

Prefetching is not unconditional. Next.js uses the Intersection Observer API to prefetch only links that are currently in the viewport. It also disables prefetching when the user has a slow network connection or has Save-Data enabled. In those cases, Next.js skips the automatic fetch.

Even when prefetching runs, Next.js only fetches the JavaScript bundle. It does not execute the code, so no additional resources from the prefetched page are requested until the user actually navigates there.

Opting out of prefetching

For routes that users rarely visit, you can avoid the download entirely by setting the prefetch prop on <Link> to false:

<Link href="/rarely-visited-page" prefetch={false}>

When a page contains multiple links, the network tab will show that bundles for links with prefetch set to true (or left at the default) are downloaded, while those with prefetch={false} are not requested at all.

Adding prefetch to a custom router

The <Link> component covers most cases, but you can build your own routing component when you need custom logic—for example, handling a form submission before navigating. Next.js exposes the router API through next/router for these scenarios.

To implement prefetching yourself, call the prefetch method that useRouter returns. A common pattern is to do this inside a useEffect hook so it runs when your custom link component renders:

useEffect(() => {
  if (prefetch) {
    router.prefetch(href);
  }
}, [prefetch, href]);

Click handling is separate. In the click handler, you can run any extra logic—such as logging a message—and then call push from the router to navigate to the href:

const handleClick = (event) => {
  event.preventDefault();
  console.log(&quot;Having fun with Next.js.&quot;);
  router.push(href);
};

A custom link component that accepts a prefetch prop works the same way as the built-in <Link>: when prefetch is true, the route's JavaScript is downloaded on render; when it is false, no prefetch happens.

Summary

With the built-in <Link> component, Next.js automatically fetches the JavaScript for linked routes that are visible in the viewport, which speeds up subsequent navigations. Custom routing components can get the same behavior by calling prefetch from useRouter. For pages that are rarely accessed, set prefetch to false to avoid unnecessary downloads.