To prefetch links in Astro, set prefetch: true in astro.config.mjs and add data-astro-prefetch to the links you want loaded early. Astro then fetches the target page in the background when the user hovers over or focuses the link, so the navigation feels close to instant. Pages that use <ClientRouter /> have prefetching on by default.
Key Takeaways
prefetch: trueturns the feature on;data-astro-prefetchopts a link in.- Strategies:
hover(default),tap,viewport,load.prefetchAll: trueprefetches every link without attributes.- Prefetching costs bandwidth, so use
viewportandloadsparingly.
Enable it
// astro.config.mjs
import { defineConfig } from 'astro/config';
export default defineConfig({
prefetch: true,
});
Then mark links:
<a href="/pricing/" data-astro-prefetch>Pricing</a>
Astro adds a small script that watches marked links and fetches their HTML when the strategy fires. The browser caches the response, so the click is served from cache.
Strategies
Set a strategy per link with the attribute value:
<a href="/docs/" data-astro-prefetch="hover">Docs</a>
<a href="/blog/" data-astro-prefetch="viewport">Blog</a>
<a href="/" data-astro-prefetch="load">Home</a>
<a href="/contact/" data-astro-prefetch="tap">Contact</a>
| Strategy | Fetches when | Use for |
|---|---|---|
hover (default) |
Pointer hovers or the link gets focus | Most navigation links |
tap |
Just before the click (pointer down) | Low-traffic links, data-saving |
viewport |
Link scrolls into view | Primary next step, e.g. “Next article” |
load |
Right after the page loads | One or two very likely destinations |
hover is a good default. The gap between hover and click is usually enough to fetch a static HTML page from a CDN.
Prefetch everything
To skip attributes entirely:
export default defineConfig({
prefetch: {
prefetchAll: true,
defaultStrategy: 'hover',
},
});
To exclude a link, set data-astro-prefetch="false". Use this for links to large downloads or pages with side effects (logout, unsubscribe).
Prefetch from code
To prefetch in response to your own logic, such as when a search result is highlighted:
<script>
import { prefetch } from 'astro:prefetch';
document.querySelector('#search')?.addEventListener('focus', () => {
prefetch('/search/');
});
</script>
prefetch() respects the user’s data saver setting, and skips prefetching on slow connections unless you pass { ignoreSlowConnection: true }.
With ClientRouter
If your layout includes <ClientRouter /> from astro:transitions, prefetching is enabled by default with prefetchAll: true. Set prefetch: false to opt out, or configure the strategy as above.
What prefetch doesn’t do
- It fetches HTML, not the whole page. Images, scripts and CSS on the target page load after navigation, unless already cached. Shared CSS and JS bundles usually are.
- It doesn’t prerender. The browser still parses and renders on click. For full prerendering in Chromium browsers, Astro has an experimental
clientPrerenderoption based on the Speculation Rules API. - It isn’t free. Every prefetch is a request. On a page with 200 links,
viewportorloadfor all of them wastes your visitors’ data and your bandwidth.
Measuring the effect
Open DevTools, Network tab, and hover a prefetched link: you’ll see the request with low priority. Then click: the document is served from the prefetch cache. On a static site behind a CDN, that typically removes the network wait from navigation entirely.
Prefetch is one part of a broader approach to speed; the Astro performance guide covers images, fonts and scripts too. For reducing JavaScript on the page itself, see lazy-loading islands. The Astro configuration docs show where prefetch sits in a theme’s config, and the full API is in the Astro prefetch guide.
FAQ
Is Astro prefetch enabled by default?
Only on pages that use <ClientRouter />. Otherwise add prefetch: true to your config.
Does prefetch hurt performance?
hover and tap add negligible cost. viewport and load on many links can waste bandwidth, so use them for one or two likely destinations.