Skip to content

feat: add preloadResources option to control what gets preloaded (code vs code + data) #7027

@gyenabubakar

Description

@gyenabubakar

What is the problem?

defaultPreload: 'intent' preloads both the route's JS chunk and runs its loaders/data fetching on hover. There's no way to preload only the code chunk without triggering data fetching.

loadRouteChunk() exists for code-only preloading, but it's imperative — there's no declarative equivalent for <Link> or the router config.

Why does this matter?

Cost: In serverless deployments (e.g., Cloudflare Workers), each loader invocation is a billed request. Static assets (JS chunks) are served for free. Preloading data on hover intent wastes compute budget since users often hover over links without clicking.

Data freshness: defaultPreloadStaleTime is not a solution for apps with low staleness tolerance. If your app needs data to be current at the time of navigation, you can't cache preloaded data — but you still want instant code loading. There's currently no way to say "preload the code so navigation is fast, but fetch data fresh when the user actually navigates."

The current workarounds are:

  • Disabling preloading entirely (defaultPreload: false) — loses the UX benefit of instant navigation
  • Building a custom Link wrapper that calls loadRouteChunk() on hover — works but fragile and requires replacing every <Link> usage

Proposed solution

Add a separate option to control what gets preloaded:

const router = createRouter({
  defaultPreload: 'intent',
  defaultPreloadResources: 'chunk', // only preload JS chunks, skip loaders
})

// or per-link
<Link to="/posts" preloadResources="chunk">Posts</Link>

Values:

  • 'all' (default) — current behavior, preloads code + runs loaders
  • 'chunk' — preloads only the JS chunk via loadRouteChunk(), skips loaders

This keeps defaultPreload responsible for when to preload (intent, viewport, render) and defaultPreloadResources for what to preload.

Alternatives considered

  • Overloading defaultPreload with a 'code' value — conflates the "when" and "what" concerns
  • A boolean preloadData: false — less extensible if more resource types are added later

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions