Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

feat(nuxt): forward destination preload hints on link prefetch - #35144

#35144
Merged
danielroe merged 4 commits into
mainnuxt/nuxt:mainfrom
feat/prefetch-preloadnuxt/nuxt:feat/prefetch-preloadCopy head branch name to clipboard
May 21, 2026
Merged

feat(nuxt): forward destination preload hints on link prefetch#35144
danielroe merged 4 commits into
mainnuxt/nuxt:mainfrom
feat/prefetch-preloadnuxt/nuxt:feat/prefetch-preloadCopy head branch name to clipboard

Conversation

@danielroe

Copy link
Copy Markdown
Member

🔗 Linked issue

resolves #34953
inspired by https://github.com/dan-hale/NuxtFaster/blob/master/plugins/preload.ts (cc: @dan-hale)

📚 Description

When <NuxtLink prefetch> (or the default visibility-based prefetch) fires for a route that has payload extraction, we already fetch the destination's _payload.json and prime its data + chunks. This PR additionally forwards any <link rel="preload"> / <link rel="modulepreload"> hints the destination has set via useHead (or via modules like @nuxt/image's <NuxtImg preload>) into the current document, downgraded to rel="prefetch" so they don't compete with the current page's critical resources.

To benefit, you need to opt-in:

export default defineNuxtConfig({
  experimental: {
    prefetchPreloadTags: true,
  },
})

Once enabled, a page like this:

<script setup lang="ts">
const { data: product } = await useFetch(`/api/products/${useRoute().params.id}`)
</script>

<template>
  <article>
    <NuxtImg :src="product.heroImage" preload />
    <h1>{{ product.name }}</h1>
  </article>
</template>

will have its hero image fetched in the background as soon as a <NuxtLink to="/product/123"> to it becomes visible (or is hovered, depending on prefetchOn), instead of waiting until the user clicks through.

@github-actions github-actions Bot added 5.x ✨ enhancement New feature or improvement to existing functionality labels May 21, 2026
Comment thread docs/3.guide/6.going-further/1.experimental-features.md Outdated
@coderabbitai

coderabbitai Bot commented May 21, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: fb42a671-9200-43c6-8dcc-f3aa701591ce

📥 Commits

Reviewing files that changed from the base of the PR and between 16342e9 and 1c8e7df.

📒 Files selected for processing (2)
  • test/basic.test.ts
  • test/fixtures/basic/app/pages/prefetch/server-components.vue
✅ Files skipped from review due to trivial changes (1)
  • test/fixtures/basic/app/pages/prefetch/server-components.vue

Walkthrough

This pull request implements the experimental prefetchPreloadTags feature: adds schema/config and generated export, records user-defined preload/modulepreload link tags during SSR into ssrContext.payload.prefetchLinks, updates payload splitting and renderer to preserve or strip that field appropriately, injects downgraded rel="prefetch" links on client prefetch with lifecycle cleanup, and includes tests, fixtures and documentation.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The pull request title clearly and concisely summarises the main change: forwarding destination preload hints during link prefetch, which is the primary objective of this changeset.
Description check ✅ Passed The pull request description comprehensively explains the feature, its purpose, configuration, and usage examples, directly relating to the changeset and linked issue #34953.
Linked Issues check ✅ Passed The code changes fully implement the objectives from issue #34953: configuration option for prefetch preload tags, payload extraction of preload heads, and integration with existing prefetch behaviour (visibility/interaction).
Out of Scope Changes check ✅ Passed All changes are directly related to the prefetchPreloadTags feature implementation; no out-of-scope modifications were introduced.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/prefetch-preload

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/schema/src/types/schema.ts`:
- Around line 1520-1528: Update the documentation for the prefetchPreloadTags
option to mention that both rel="preload" and rel="modulepreload" link hints are
forwarded (and downgraded to rel="prefetch"), not just preload; reference the
implementation by noting FORWARDED_RELS includes 'preload' and 'modulepreload'
(see the constant in prefetch-preload-tags.server.ts) and adjust the description
text in the prefetchPreloadTags JSDoc accordingly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 5b67d1f5-b2d4-457d-97bc-dab1e06b0bd0

📥 Commits

Reviewing files that changed from the base of the PR and between 1d0de41 and 96c4278.

⛔ Files ignored due to path filters (2)
  • packages/nuxt/package.json is excluded by !**/package.json
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml, !pnpm-lock.yaml
📒 Files selected for processing (14)
  • docs/3.guide/6.going-further/1.experimental-features.md
  • packages/nitro-server/src/runtime/handlers/renderer.ts
  • packages/nitro-server/src/runtime/utils/renderer/payload.ts
  • packages/nuxt/meta.js
  • packages/nuxt/src/app/nuxt.ts
  • packages/nuxt/src/app/plugins/payload.client.ts
  • packages/nuxt/src/app/plugins/prefetch-preload-tags.server.ts
  • packages/nuxt/src/core/nuxt.ts
  • packages/nuxt/src/core/templates.ts
  • packages/schema/src/config/experimental.ts
  • packages/schema/src/types/schema.ts
  • test/basic.test.ts
  • test/fixtures/basic/app/pages/prefetch/server-components.vue
  • test/fixtures/basic/nuxt.config.ts

Comment on lines +1520 to +1528
/**
* When a `<NuxtLink>` is prefetched and the destination route has a `_payload.json`, forward any `<link rel="preload">` hints that the destination set via `useHead` (or via modules like `@nuxt/image`'s `<NuxtImg preload>`) into the current document.
*
* The forwarded links are downgraded from `rel="preload"` to `rel="prefetch"` so they don't compete with the current page's critical resources. Only user-defined head tags are forwarded; build-time JS/CSS chunk preloads are not.
*
* @default false
* @see [Issue #34953](https://github.com/nuxt/nuxt/issues/34953)
*/
prefetchPreloadTags: boolean

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Documentation should mention modulepreload in addition to preload.

The documentation currently states "forward any <link rel="preload"> hints" and mentions downgrading from rel="preload", but the implementation (in prefetch-preload-tags.server.ts line 11) forwards both preload and modulepreload via FORWARDED_RELS = new Set(['preload', 'modulepreload']).

📝 Suggested documentation clarification
     /**
-     * When a `<NuxtLink>` is prefetched and the destination route has a `_payload.json`, forward any `<link rel="preload">` hints that the destination set via `useHead` (or via modules like `@nuxt/image`'s `<NuxtImg preload>`) into the current document.
+     * When a `<NuxtLink>` is prefetched and the destination route has a `_payload.json`, forward any `<link rel="preload">` or `<link rel="modulepreload">` hints that the destination set via `useHead` (or via modules like `@nuxt/image`'s `<NuxtImg preload>`) into the current document.
      *
-     * The forwarded links are downgraded from `rel="preload"` to `rel="prefetch"` so they don't compete with the current page's critical resources. Only user-defined head tags are forwarded; build-time JS/CSS chunk preloads are not.
+     * The forwarded links are downgraded from `rel="preload"` or `rel="modulepreload"` to `rel="prefetch"` so they don't compete with the current page's critical resources. Only user-defined head tags are forwarded; build-time JS/CSS chunk preloads are not.
      *
      * `@default` false
      * `@see` [Issue `#34953`](https://github.com/nuxt/nuxt/issues/34953)
      */
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/**
* When a `<NuxtLink>` is prefetched and the destination route has a `_payload.json`, forward any `<link rel="preload">` hints that the destination set via `useHead` (or via modules like `@nuxt/image`'s `<NuxtImg preload>`) into the current document.
*
* The forwarded links are downgraded from `rel="preload"` to `rel="prefetch"` so they don't compete with the current page's critical resources. Only user-defined head tags are forwarded; build-time JS/CSS chunk preloads are not.
*
* @default false
* @see [Issue #34953](https://github.com/nuxt/nuxt/issues/34953)
*/
prefetchPreloadTags: boolean
/**
* When a `<NuxtLink>` is prefetched and the destination route has a `_payload.json`, forward any `<link rel="preload">` or `<link rel="modulepreload">` hints that the destination set via `useHead` (or via modules like `@nuxt/image`'s `<NuxtImg preload>`) into the current document.
*
* The forwarded links are downgraded from `rel="preload"` or `rel="modulepreload"` to `rel="prefetch"` so they don't compete with the current page's critical resources. Only user-defined head tags are forwarded; build-time JS/CSS chunk preloads are not.
*
* `@default` false
* `@see` [Issue `#34953`](https://github.com/nuxt/nuxt/issues/34953)
*/
prefetchPreloadTags: boolean
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/schema/src/types/schema.ts` around lines 1520 - 1528, Update the
documentation for the prefetchPreloadTags option to mention that both
rel="preload" and rel="modulepreload" link hints are forwarded (and downgraded
to rel="prefetch"), not just preload; reference the implementation by noting
FORWARDED_RELS includes 'preload' and 'modulepreload' (see the constant in
prefetch-preload-tags.server.ts) and adjust the description text in the
prefetchPreloadTags JSDoc accordingly.

@danielroe
danielroe requested a review from harlan-zw May 21, 2026 13:23
@pkg-pr-new

pkg-pr-new Bot commented May 21, 2026

Copy link
Copy Markdown

Open in StackBlitz

@nuxt/kit

npm i https://pkg.pr.new/@nuxt/kit@35144

@nuxt/nitro-server

npm i https://pkg.pr.new/@nuxt/nitro-server@35144

nuxt

npm i https://pkg.pr.new/nuxt@35144

@nuxt/rspack-builder

npm i https://pkg.pr.new/@nuxt/rspack-builder@35144

@nuxt/schema

npm i https://pkg.pr.new/@nuxt/schema@35144

@nuxt/vite-builder

npm i https://pkg.pr.new/@nuxt/vite-builder@35144

@nuxt/webpack-builder

npm i https://pkg.pr.new/@nuxt/webpack-builder@35144

commit: 1c8e7df

@codspeed-hq

codspeed-hq Bot commented May 21, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 20 untouched benchmarks
⏩ 3 skipped benchmarks1


Comparing feat/prefetch-preload (1c8e7df) with main (48b15c2)

Open in CodSpeed

Footnotes

  1. 3 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@danielroe
danielroe merged commit bb4e7ef into main May 21, 2026
32 of 33 checks passed
@danielroe
danielroe deleted the feat/prefetch-preload branch May 21, 2026 21:33
@github-actions github-actions Bot mentioned this pull request May 21, 2026
5 tasks
@github-actions github-actions Bot mentioned this pull request May 22, 2026
davidstackio pushed a commit to davidstackio/nuxt that referenced this pull request May 30, 2026
danielroe added a commit that referenced this pull request Jun 2, 2026
danielroe added a commit that referenced this pull request Jun 2, 2026
danielroe added a commit that referenced this pull request Jun 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

5.x ✨ enhancement New feature or improvement to existing functionality

Projects

None yet

Development

Successfully merging this pull request may close these issues.

NuxtLink: Prefetch Preload Tags

2 participants

Morty Proxy This is a proxified and sanitized view of the page, visit original site.