ADR-028: Prefetch Strategy — @astrojs/prefetch
Status
Section titled “Status”Superseded — @astrojs/prefetch was deprecated in Astro 3.5 and removed in Astro 4.0. The project now uses Astro’s built-in prefetch: true config option in astro.config.mjs, which provides equivalent hover/focus-based prefetching natively. See Astro Prefetch Guide for the current approach.
Context
Section titled “Context”The starter includes @astrojs/prefetch in astro.config.mjs. This integration adds a small JavaScript snippet (~1KB) that prefetches pages when a user hovers over or focuses an internal link, making subsequent navigations feel instant.
This is an undocumented addition that adds JavaScript to every page — a tension with the zero-JS philosophy. This ADR justifies the inclusion and defines the configuration defaults.
Decision Drivers
Section titled “Decision Drivers”- Perceived performance: Prefetching eliminates the network round-trip on navigation, making the site feel faster even when Lighthouse scores are already high
- JS budget: The addition must be minimal — under 2KB gzipped
- Zero-JS philosophy: Any JavaScript addition requires explicit justification (per ADR-001 pattern)
- Progressive enhancement: Prefetching is purely additive — pages load correctly without it
- Works with View Transitions: Prefetch + ClientRouter (ADR-009) together produce near-instant navigation
Considered Options
Section titled “Considered Options”Option 1: No prefetching
Section titled “Option 1: No prefetching”Pros:
- Strictly zero JavaScript for navigation
- No speculative network requests
Cons:
- Full network round-trip on every navigation
- Noticeably slower perceived performance on multi-page sites
- Wastes the benefit of static hosting (files are already on CDN edge)
Option 2: @astrojs/prefetch with intentSelector (hover/focus) — chosen
Section titled “Option 2: @astrojs/prefetch with intentSelector (hover/focus) — chosen”Pros:
- Prefetch only triggers on user intent (hover/focus), not on page load
- No wasted bandwidth for links the user never clicks
- ~1KB gzipped — negligible JS budget impact
- Works automatically with all
<a>tags pointing to internal routes
Cons:
- Adds JavaScript to every page
- Hover-based prefetch doesn’t help on touch-only devices (touch triggers click, not hover)
Option 3: <link rel="prefetch"> in <head> (manual)
Section titled “Option 3: <link rel="prefetch"> in <head> (manual)”Pros:
- No JavaScript at all — pure HTML hint
- Browser decides whether to act on it
Cons:
- Must be manually added per page
- No dynamic intent detection
- Prefetches unconditionally on page load (wastes bandwidth)
Option 4: Speculation Rules API
Section titled “Option 4: Speculation Rules API”Pros:
- Native browser API, no JavaScript library
- Supports prerendering (not just prefetching)
Cons:
- Chrome-only as of 2026 — not cross-browser
- Prerendering has privacy implications (executes page JS before user navigates)
- Not yet suitable as a default
Decision
Section titled “Decision”Keep @astrojs/prefetch with default intentSelector behaviour (hover + focus triggers prefetch).
The ~1KB cost is justified by the significant perceived performance improvement on multi-page navigation. This is consistent with the ADR-009 decision to include ClientRouter (~2-3KB) for the same reason: small, justified JS additions that improve perceived performance are acceptable when they degrade gracefully.
Configuration
Section titled “Configuration”import prefetch from '@astrojs/prefetch';
export default defineConfig({ integrations: [ prefetch(), // defaults: intentSelector triggers on hover/focus ],});No custom configuration is needed. The default behaviour is correct for this use case.
Touch Device Consideration
Section titled “Touch Device Consideration”On touch devices, hover events don’t fire before click. Prefetch therefore provides no benefit on touch-only interactions. This is acceptable — the site loads correctly without prefetch, and touch users on fast connections won’t notice the difference. Touch users on slow connections benefit from the static CDN delivery regardless.
Consequences
Section titled “Consequences”Positive
Section titled “Positive”- Near-instant navigation when combined with ClientRouter (ADR-009)
- Zero configuration required
- Gracefully degrades — pages work without it
Negative
Section titled “Negative”- Adds ~1KB JavaScript to every page
- No benefit on touch-only devices
- Speculative network requests may be unwanted on metered connections (mitigated by intent-based triggering)
Neutral
Section titled “Neutral”- Total JavaScript from prefetch + ClientRouter: ~4KB gzipped — well within the 160KB budget
- Speculation Rules API should be re-evaluated when cross-browser support improves
Validation
Section titled “Validation”- Bundle size:
@astrojs/prefetchcontribution must remain under 2KB gzipped - Lighthouse: No regression in Performance score from prefetch script
- Network tab: Prefetch requests only fire on hover/focus, not on page load
References
Section titled “References”- @astrojs/prefetch Documentation
- Speculation Rules API (MDN)
- ADR-009: ClientRouter and View Transitions
- ADR-001: Preact Island Usage Policy — JS justification pattern
Enforcement
Section titled “Enforcement”Not enforced — this record’s status is Superseded; only Accepted ADRs are binding (see the status table in the ADR README and ADR-039).
Date: 2026-02-18
Participants: Template maintainers
Outcome: Superseded (replaced by built-in prefetch: true config)