How does Next.js 16 prefetch behave?
The prefetch prop on <Link> determines what gets loaded before and after a click — and whether your loading state ever renders at all. This matrix covers all combinations of route type, loading boundary presence, and prefetch behaviour.
force-dynamic | loading.tsx ✓ | varies: prefetch prop
loading.tsx renders immediately on click — users see a spinner while page data loads in the background.
Try demoNavigation is delayed until the server responds. loading.tsx is fetched at click time — and may never render if the page loads first.
Try demoEverything is loaded on hover. Clicking navigates instantly to the full page — no loading state shown at all.
Try demoforce-dynamic | loading.tsx ✗ | varies: prefetch prop
No loading boundary means no partial prefetch. Clicking blocks navigation on the current page until the server responds — no loading state is ever shown.
Try demoprefetch=true forces a full prefetch even without loading.tsx. Navigation is instant but no loading state is possible — the full page data must be fetched upfront on hover.
Try demoforce-dynamic | loading.tsx in parent segment only | prefetch={null}
The partial prefetch only reaches the nearest loading boundary — which is in the parent segment. The child's page.tsx is still fetched on click. Placing loading.tsx closer to the page gives more granular control.
Try demostatic render (no force-dynamic) | varies: prefetch | varies: loading.tsx
Static routes are always fully prefetched — layout, loading.tsx, and page data. The loading state is prefetched but never shown because navigation is instant. Router Cache TTL: 5 min.
Try demoprefetch={false} disables prefetching even for static routes. The page is fetched from the edge CDN on click — fast, but not instant. No loading state is shown.
Try demoprefetch={null} is usually right
Prefetch is triggered by viewport entry. Next.js loads only the shell — fast and cheap. The loading state renders instantly on click while page data streams in.
prefetch={false} has a trap
Both loading.tsx and page.tsx are fetched on click. If page loads first, the loading state never shows — wasted bandwidth.
prefetch={true} is expensive
Pre-fetches everything on viewport entry, including all page data. Instant navigation — but costs bandwidth for every link in view.
No loading.tsx blocks navigation
Without a loading boundary, partial prefetch is impossible. The browser stays on the current page until the server fully responds.
Static routes are fully prefetched by default
With prefetch={null} or prefetch={true}, Next.js fully prefetches static routes on viewport entry — layout, loading.tsx, and page data. Setting prefetch={false} still disables prefetching.
Boundary placement matters
The partial prefetch stops at the nearest loading.tsx. Place it close to the page component for the most granular loading control.