Skip to content

feat(pages): add an app-wide default prefetch strategy for Link - #694

Merged
cpojer merged 2 commits into
voidzero-dev:mainfrom
yangshun:feat/link-default-prefetch-strategy
Nov 4, 2026
Merged

cpojer merged 2 commits into
voidzero-dev:mainfrom
yangshun:feat/link-default-prefetch-strategy

Conversation

@yangshun

@yangshun yangshun commented Nov 4, 2026 •

Copy link
Copy Markdown
Collaborator

What this adds

Until now, a Link prefetched only when it set prefetch itself, so an app that wanted hover prefetching everywhere had to add the prop to every Link. Adapter plugins now take prefetch.defaultStrategy, next to the existing hoverDelay and cacheFor:

voidReact({ prefetch: { defaultStrategy: 'hover' } });
  • Same values as the prop: true, false, 'hover' | 'click' | 'mount' | 'visible', or an array of them. The default is false, so existing apps don't change, and void init doesn't turn it on. I propose changing the default for new apps. See below.
  • A Link's own prefetch replaces the default. Values aren't merged, so a Link can drop a strategy the default includes. prefetch={false} opts that one Link out, and true still means 'hover'.
  • Only GET links use the default. Links with a non-GET method or reloadDocument skip it rather than throwing. An explicit prefetch on a POST Link still throws, as before.
  • Invalid values fail when the plugin is configured, with an error that names prefetch.defaultStrategy and lists the accepted values.

Behavior change: no prefetch for other sites

prefetchLink now skips URLs on another origin. The router matches only the path, so a prefetching Link to https://example.com/users would have loaded this app's /users page. This already affected explicit prefetch. With an app-wide default it would have affected most external links.

Open questions

  1. prefetch: { defaultStrategy: true } in the config can look a bit weird, but it's aligned with the Link instance prefetch values. Lemme know if I should remove true as an accepted value for the config.
  2. Should we make prefetch.defaultStrategy: 'hover' for new apps? I personally think this is the most balanced default. What other frameworks do:
    • Astro sets to hover if you turn prefetching on
    • Next.js defaulted to visible for production and it gives them good business. I didn't like it and there was no global-way to set it.

Testing

  • Unit tests:
    • linkPrefetchStrategies: the default, replacement by the prop, opt-out, and non-GET links
    • prefetchLink: skipping other origins and non-HTTP schemes
    • resolvePrefetchConfig: defaults and validation
    • the router and its facade exposing the default
  • The adapter contract test checks that all four generated client entries pass the default.
  • A new happy-dom React test mounts a real Link under a router default. Vue, Svelte and Solid have no DOM test setup, so their Links are covered by typecheck, the shared unit tests and the generated-entry test.
  • vp run check passes, and vp run test passes for all 536 affected test files.
  • In the full vp test run, three files timed out under load: tanstack-start dev (the server needed 19 s against a 20 s limit), plugin-cloudflare-v2 and worker-build-node-require (5 s each). None touch Link or prefetch code, and all three pass when rerun on their own.

yangshun and others added 2 commits November 4, 2026 08:24
Adapter plugins accept `prefetch.defaultStrategy`, which takes the same
values as Link's `prefetch` prop and defaults to `false`. A Link without
its own `prefetch` uses it; a Link's own value replaces it, and
`prefetch={false}` opts out. The default applies only to GET links that
don't use `reloadDocument`, so mutation links keep working. An invalid
strategy fails when the plugin is configured.

Links to other sites are no longer prefetched. The router matches only
the path, so they would have prefetched a same-path page of this app.

The Pages guide gains a short Prefetching section, and the Pages API
reference documents every strategy, `cacheFor`, and the plugin options.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…fetch-strategy

# Conflicts:
#	docs/guide/pages-routing/overview.md
#	packages/svelte/src/runtime/Link.svelte
#	packages/void/src/pages/link.ts
#	packages/vue/src/runtime/link.ts

@cpojer cpojer left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@cpojer
cpojer merged commit f10f68a into voidzero-dev:main Nov 4, 2026
18 checks passed
@yangshun
yangshun deleted the feat/link-default-prefetch-strategy branch November 4, 2026 04:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants