Skip to content

chore(deps): update nuxt core to v4 - #59

Open
renovate[bot] wants to merge 2 commits into
mainfrom
renovate/major-nuxt
Open

chore(deps): update nuxt core to v4#59
renovate[bot] wants to merge 2 commits into
mainfrom
renovate/major-nuxt

Conversation

@renovate

@renovate renovate Bot commented Jul 16, 2025

Copy link
Copy Markdown
Contributor

ℹ️ Note

This PR body was truncated due to platform limits.

This PR contains the following updates:

Package Change Age Confidence
@nuxt/test-utils 3.21.04.1.0 age confidence
nuxt (source) ^3.16.1^4.0.0 age confidence

Warning

Some dependencies could not be looked up. Check the Dependency Dashboard for more information.


Release Notes

nuxt/test-utils (@​nuxt/test-utils)

v4.1.0

Compare Source

4.1.0 is the next minor release.

👉 Changelog

compare changes

🚀 Enhancements
  • e2e: Silence server logs and allow customising log level (#​1735)
  • runtime: Improve app.root and app.teleports html tag setup (#​1726)
🩹 Fixes
  • e2e: Add warning message for e2e in nuxt vitest setup (#​1691)
  • runtime-utils: Ensure RouterLink stub works with pages: false (#​1687)
  • config: Patch ssr.resolve.conditions to remove import (#​1732)
  • config: Browser setup in defineVitestProject (#​1724)
  • config: Inline config for useRuntimeConfig() composable (#​1737)
  • config: Nested browser-mode Nuxt Vitest projects with viteEnvironmentApi (#​1708)
📦 Build
🏡 Chore
  • Drop pkg.pr.new nitro resolution (#​1681)
  • Migrate to pnpm v11 (#​1701)
  • Move h3-next to optional dependencies (#​1733)
✅ Tests
  • Add test for autoImport: false (#​1688)
🤖 CI
  • Add agent-scan workflow to flag bot-authored PRs (13dd49cde)
  • Migrate agentscan-action to v2 (08f8ee220)
❤️ Contributors

v4.0.3

Compare Source

4.0.3 is the next patch release.

👉 Changelog

compare changes

🩹 Fixes
  • runtime-utils: Lazily import root-component in mount + render helpers (#​1665)
  • runtime-utils: Insert compilerOptions conditionally (#​1659)
  • config: Enable sourcemaps when vitest coverage is enabled (#​1674)
  • module: Exclude test files from Nuxt plugin registration (#​1666)
  • runtime-utils: Provide NuxtLink isActive slot props (#​1640)
  • e2e: Wait for HTTP readiness before resolving startServer (#​1675)
🏡 Chore
❤️ Contributors

v4.0.2

Compare Source

👉 Changelog

compare changes

🩹 Fixes
  • config: Respect override dev value (#​1602)
🤖 CI
  • Use pnpm publish to resolve workspace dependencies (#​1651)
❤️ Contributors

v4.0.1

Compare Source

👉 Changelog

compare changes

🩹 Fixes
  • config: Rename deps.optimizer.web to client for vitest4 (#​1593)
  • runtime-utils: Fix mockNuxtImport types when using string target (#​1592)
  • config: Pass non-project options for non-nuxt simple setup (#​1582)
  • config: Do not import defineConfig from vite (1aa5e8748)
  • runtime: Handle ResourceLoader removal in jsdom v28 (#​1611)
  • config,vitest-environment: Directly import peerDeps (#​1617)
  • runtime-utils: Align mount options merge w/ vue-test-utils (#​1610)
  • vitest-environment: Avoid vitest/environments import warning (#​1627)
  • runtime: Avoid error when vue/test-utils is not installed (#​1646)
  • config: Prefer project h3 version if present (#​1641)
🏡 Chore
  • Bump vitest-environment-nuxt versions (f5ec72127)
  • Use workspace dependency (14fb254a7)
  • Example playwright config improve type annotation for devices (#​1581)
  • pkg-pr-new prerelease vitest-environment-nuxt (#​1601)
  • Allow explicit any (633c93c2a)
  • Switch unit test target to dir and move type unit tests to test:types (#​1618)
  • Update lockfile (8306abf00)
✅ Tests
  • Add failing test for stubbed global provide (#​1314)
  • Update assertions deprecated in vitest 4.1 (#​1629)
  • Change example/workspace to use glob based projects setup (#​1585)
🤖 CI
  • Pin github actions to full-length commit shas (2832fd6d5)
  • Avoid checkout for reproduction comment (e4e67ab09)
  • Rename workflow (99318b9fc)
  • Correctly publish pkg-pr-new prerelease (#​1598)
❤️ Contributors

v4.0.0

Compare Source

4.0.0 is the next major release.

👀 Highlights

We're releasing Nuxt Test Utils v4, with support for Vitest v4. 🚀

Better mocking support

The biggest improvement in this release is how mocking works. Nuxt initialization has been moved from setupFiles to the beforeAll hook (#​1516), which means vi.mock and mockNuxtImport calls now take effect before Nuxt starts. This fixes a long-standing issue where mocks for composables used in middleware or plugins wouldn't apply reliably (#​750, #​836, #​1496).

On top of that, mockNuxtImport now passes the original implementation to the factory function (#​1552), making partial mocking much more natural:

mockNuxtImport('useRoute', original => vi.fn(original))

it('my test', async () => {
  vi.mocked(useRoute).mockImplementation(
    (...args) => ({ ...vi.mocked(useRoute).getMockImplementation()!(...args), path: '/mocked' }),
  )

  const wrapper = await mountSuspended(MyComponent)
  expect(wrapper.find('#path').text()).toBe('/mocked')
})
registerEndpoint improvements

registerEndpoint now works correctly with query parameters in URLs (#​1560), and endpoints registered in setup files are no longer lost when modules reset (#​1549).

🚧 Migration

@nuxt/test-utils v4 contains a few breaking changes, almost all related to requiring at least vitest v4 as a peer dependency (if you are using vitest). It replaces vite-node with Vite's native Module Runner and simplifies pool configuration.

This will mean improvements for test performance and mocking, but does require some changes to your test code.

[!TIP]
Most of the changes below are straightforward. The biggest thing to watch out for is code that runs at the top level of a describe block — see below.

Update your dependencies

Update vitest and its companion packages together:

{
  "devDependencies": {
-   "@nuxt/test-utils": "^3.x",
-   "vitest": "^3.x",
-   "@vitest/coverage-v8": "^3.x"
+   "@nuxt/test-utils": "^4.0",
+   "vitest": "^4.0",
+   "@vitest/coverage-v8": "^4.0"
  }
}
Peer dependencies

We've tightened peer dependency ranges. You may need to update some of these:

Dependency v3 v4
vitest ^3.2.0 ^4.0.2
happy-dom * >=20.0.11
jsdom * >=27.4.0
@jest/globals ^29.5.0 || >=30.0.0 >=30.0.0
@cucumber/cucumber ^10.3.1 || >=11.0.0 >=11.0.0
@testing-library/vue ^7.0.0 || ^8.0.1 ^8.0.1
Later environment setup

This is the change that might require most change in your tests. Because we've moved the nuxt environment setup into beforeAll, this means composables called at the top level of a describe block will fail with [nuxt] instance unavailable.

// Before (worked in vitest v3)
describe('my test', () => {
  const router = useRouter() // ran lazily, after environment setup
  // ...
})

// After (vitest v4)
describe('my test', () => {
  let router: ReturnType<typeof useRouter>

  beforeAll(() => {
    router = useRouter() // runs after environment setup
  })
  // ...
})

This applies to useRouter(), useNuxtApp(), useRoute(), and any other Nuxt composable or auto-import.

[!TIP]
If you only need the value within individual tests, beforeEach or directly within the test works too.

Stricter mock exports

If you use vi.mock with a factory function, accessing an export that the factory doesn't return will now throw an error instead of silently returning undefined.

// Before: accessing `bar` would silently return undefined
vi.mock('./module', () => ({ foo: 'mocked' }))

// After: accessing `bar` throws
// Fix: use importOriginal to include all exports
vi.mock('./module', async (importOriginal) => ({
  ...await importOriginal(),
  foo: 'mocked',
}))

[!NOTE]
If you're mocking a virtual module (like #build/nuxt.config.mjs) where importOriginal can't resolve the real module, you might need to explicitly list all accessed exports in your mock factory.

Other changes

For the full list, see the vitest v4 migration guide.

👉 Changelog

compare changes

🚀 Enhancements
  • deps: ⚠️ Upgrade to vitest v4 (#​1481)
  • deps: ⚠️ Drop official support for older versions of test runners + dom environments (31fdc262a)
  • runtime-utils: Pass original to mockNuxtImport factory (#​1552)
  • runtime: ⚠️ Change nuxt start timing to beforeAll hook (#​1516)
  • e2e: Support setup and teardown timeouts in setupBun (#​1578)
🩹 Fixes
  • runtime: Handle optional chaining vueWrapper plugin installed check (#​1547)
  • runtime-utils: Keep endpoints from registerEndpoint in setup file (#​1549)
  • runtime-utils: Support registerEndpoint with query params (#​1560)
  • runtime-utils: Avoid local variable in mockNuxtImport macro (#​1564)
  • runtime-utils: Add missing nextTick import (#​1563)
  • Pin h3-next to patch (1ff3bbb91)
  • playwright: Bump windows timeout (63e39b7c9)
  • config: Respect include options in non nuxt environment simple setup (#​1570)
💅 Refactors
  • module: Use @nuxt/devtools-kit for devtools hooks (426e0b537)
  • runtime: Remove unnecessary querySelector (#​1577)
📖 Documentation
🏡 Chore
  • Allow changelog update util to return major bump (9e86cadab)
  • Make app-vitest follow advised setup guidelines (#​1542)
  • Update lockfile (6d798b5e1)
  • config: Migrate Renovate config (#​1568)
  • Add test utils setup to .nuxtrc (b4021dee4)
✅ Tests
  • Avoid running root test script twice (44f6bd396)
⚠️ Breaking Changes
  • deps: ⚠️ Upgrade to vitest v4 (#​1481)
  • deps: ⚠️ Drop official support for older versions of test runners + dom environments (31fdc262a)
  • runtime: ⚠️ Change nuxt start timing to beforeAll hook (#​1516)
❤️ Contributors

v3.23.0

Compare Source

3.23.0 is the next minor release.

👉 Changelog

compare changes

🚀 Enhancements
  • runtime-utils: Support h3 v2 (#​1515)
  • module: Add install wizard when freshly installed (#​1538)
🩹 Fixes
  • e2e: Ensure $fetch is not typed as any (1f4754ea9)
🏡 Chore
✅ Tests
  • Add cleanup to resolve-config tests (#​1537)
🤖 CI
  • Prepare build environment in autofix workflow (2c0864ed6)
❤️ Contributors

v3.22.0

Compare Source

3.22.0 is the next minor release.

👉 Changelog

compare changes

🚀 Enhancements
  • runtime-utils: Unify logic of mount + render helpers (#​1522)
  • module: Run vitest in separate process (#​1524)
  • runtime-utils: Allow skipping initial route change (fd77ec066)
  • runtime: Skip route sync emulation when NuxtPage exists (#​1530)
🔥 Performance
  • module: Skip nuxt-root stub plugin when building (#​1512)
🩹 Fixes
  • runtime-utils: Reject promise on error render + mount helpers (#​1503)
  • runtime-utils: Support new .sync method for syncing route (1148c3cf1)
  • e2e: Always override global env options with inline options (c8f881b3d)
  • runtime-utils: Avoid missing render warn on reject render + suspend helpers (#​1520)
  • e2e: Use server.deps rather than deps (2b3c86921)
  • config: Also call sync() in initial setup (ec555192c)
  • module: Use devtools:before hook instead of direct config check (#​1532)
  • config: Do not override vitest root with nuxt rootDir (#​1531)
💅 Refactors
  • runtime-utils: Do not export addCleanup (86b4998bb)
  • module: Extract nuxt environment options plugin (5ada22a9f)
📖 Documentation
  • Fix link to module authors testing guide (#​1511)
🏡 Chore
✅ Tests
  • Use local kit version for module (79f1e14d5)
  • Add defaultLocale in i18n test (059988fc3)
  • Avoid definePageMeta compiler-hint warning (#​1523)
🤖 CI
❤️ Contributors
nuxt/nuxt (nuxt)

v4.5.2

Compare Source

v4.5.1

Compare Source

⚠️ This is a security release. We recommend upgrading as soon as possible with npx nuxt upgrade --dedupe.

It fixes server-side RCE and unauthorized component instantiation via server island props, a route rule authorization bypass, server component DoS, cross-user payload disclosure on cached pages, and dev server path disclosure. Refreshing your lockfile also pulls in @nuxt/devtools@3.3.1, which fixes a separate critical development-only RCE.

If you already upgraded for the earlier route rule advisory (CVE-2026-53721), you still need this release: one of the fixes addresses a regression introduced by that fix.

If you use the cache, swr or isr route rules, purge any CDN or edge cache after upgrading; a leaked _payload.json may already be cached upstream.

Full details: Nuxt Security Patch Releases and GitHub Security Advisories.

👉 Changelog

compare changes

🔥 Performance
  • nitro: Replace island teleports in a single html pass (#​35515)
  • nuxt: Add vue.optionsApi and disable it for v5+ (#​35791)
  • nuxt: Without pages, skip client plugins that require routing (#​35794)
  • nuxt: Skip payload revival plugin when ssr: false (#​35782)
🩹 Fixes
  • nitro: Read rspack dev output fs lazily for server entry (#​35740)
  • rspack,webpack: Resolve loaders and runtime deps from nuxt dirs (#​35568)
  • nuxt: Return global route for useRoute in detached effect scope (#​35659)
  • nuxt: Ignore custom name or path when reusing an existing page in pages:extend (#​35661)
  • nuxt: Render client components in nested server components (#​35669)
  • nuxt: Preserve explicit useFetch method inference (#​35671)
  • nuxt: Revalidate cached route payloads instead of using force-cache (#​35672)
  • nuxt: Correct default export detection in plugin metadata (#​35676)
  • nuxt: Clear hide/reset timeouts in set() (#​35534)
  • kit,nuxt,rspack,schema,webpack: Add .mts file extension in resolver (#​33845)
  • nuxt: Preserve trailing slash in NuxtLink href when unset (#​35501)
  • nuxt: Don't cross-pollute useAsyncData cache on reactive key change (#​35656)
  • nuxt: Filter plugin dependencies by build target (#​35682)
  • nuxt: Reload real page module on HMR of JSX render-function pages (#​35678)
  • nuxt: Resolve @unhead/vue/* from nuxt's dependency tree (#​35690)
  • kit: Surface module load errors instead of masking as missing (#​35497)
  • nuxt: Type auto-imported $fetch with nitro's $Fetch (#​35704)
  • nuxt: Don't reference app config sources in shared and node tsconfigs (#​35673)
  • vite: Resolve SSR inlined CSS module class name mismatch (#​35610)
  • nuxt: Generate layout types even when pages module is disabled (#​35717)
  • nitro: Skip resource hints for stylesheets already rendered as blocking links (#​35691)
  • kit: Dedupe layers that are both auto-scanned and explicitly extended (#​35712)
  • nuxt: Don't apply scroll behaviour after a subsequent nav (#​35719)
  • vite: Ensure server sourcemap-preserver plugin actually runs (#​35680)
  • vite: Preserve css suffix when extracting ssr inline styles (#​35714)
  • nuxt: Watch external component directories in development (#​35652)
  • nuxt: Don't exclude client entry module from style extraction (#​35720)
  • nuxt: Amend cleanup command in NUXT_B7014 error message (#​35735)
  • nuxt: Only pull in vue-router when there are island pages (#​35739)
  • vite: Suppress external warnings for internal vite-node paths (#​35744)
  • nuxt: Use scope-aware oxc parser for auto-imports (#​35743)
  • nuxt: Sync layout meta during middleware on SSR (#​35633)
  • nitro: Add alias for h3 that pins it to the version nuxt depends on (#​35774)
  • nuxt: Preserve query params in cached payload extraction (#​35696)
  • nuxt: Mirror runtime route tree in generated typed-router types (#​35788)
  • nuxt: Warn when an imports preset from cannot be resolved (#​35799)
  • kit: Avoid mutating layer configs when resolving options (#​35729)
  • nuxt: Convert inline route rules exactly or drop with a warning (#​35455)
  • nitro,nuxt,vite: Dedupe and normalise global css links in dev (#​35834)
  • vite: Register template HMR plugin on dev servers (929c6c138)
  • nuxt: Remove dev error overlay when error is cleared (#​35821)
  • rspack,webpack: Resolve bundled postcss defaults from builder (#​35823)
  • schema: Normalise slashes in app.buildAssetsDir (#​35833)
  • nitro: Bound island props and v-for to prevent unauthenticated DoS (4e35ae9ba)
  • nitro: Confine runtime payload cache to prerendering (ac9b41a36)
  • nuxt: Case-fold route rule keys to match folded lookups (ad624a75a)
  • nitro: Require loopback peer for chrome devtools workspace endpoint (0769c4f9b)
  • nuxt: Reject reserved template island prop under runtime compiler (ee6c84633)
  • nuxt: Reject top-level as prop for islands (581651ff3)
💅 Refactors
  • nuxt: Use tick based debounce for asyncData executes (#​34151)
  • kit,nuxt: Replace semver with verkit (#​35713)
  • rspack,webpack: Use DI model to split builders (#​35751)
📖 Documentation
  • Add dev container setup guide (#​35665)
  • Fix dev container setup guide (#​35666)
  • Add explanation of 200.html and 404.html SPA fallbacks (#​34483)
  • Expand payload extraction documentation (#​35648)
  • Clarify NuxtLink componentName is the internal (devtools) name (#​35658)
  • Add example for components dir pattern option (#​35663)
  • Require a single root element (#​35677)
  • Add reason for why you should never import Vue app code in nitro code (#​34481)
  • Document disabling code-splitting with codeSplitting: false (#​35683)
  • Document nuxt-client caveat for non-SFC components (#​35654)
  • Clarify favicon does not use cdnURL by default (#​35681)
  • Standardize section order and headings across docs (#​35685)
  • Clarify onPrehydrate example comment (#​35684)
  • Add useId as a known limitation of nuxt island (#​35693)
  • Recommend status over pending in data fetching (#​35694)
  • Fill gaps in API minimalVersion badges after #​34485 (#​35708, #​34485)
  • Explain dynamic asset paths (#​35695)
  • Document runtimeConfig env var casting edge cases (#​35709)
  • Clarify module dependency resolution (#​35718)
  • Add more writing guidelines (#​35662)
  • Add note with alternatives to using remote layers (#​35721)
  • Use nuxt rather than nuxi (8891e179c)
  • Document relative baseURL workarounds (#​34004)
  • Warn about runtimeCompiler security best practices (449b63ab1)
  • Warn about validating server component props (2c981cb07)
📦 Build
  • nitro: Re-export type from augments to preserve module (dac937675)
  • nuxt: Remove .ts file extension from runtime/ imports (#​35689)
  • ui-templates: Commit generated ui template files (#​35770)
🏡 Chore
  • Add extension 🤦 (d595fb3d4)
  • Move to pnpm catalogs (#​35748)
  • Update knip config, resolve issues, and run in ci (#​35742)
  • Ignore @nuxt/telemetry in knip (9824d4f10)
  • ui-templates: Pass config file path to unocss (34e7a810d)
  • Allow regenerating lockfile in release script (c31389df3)
  • nuxt: Bump @nuxt/devtools to v3.3.1 (#​35815)
  • Ensure types are setup before unit tests (784d8f700)
  • Simplify knip configuration (#​35827)
✅ Tests
  • Reproduce duplicate CSS in shared chunks (#​35649)
  • Prepare fixtures automatically before fixture and e2e runs (e8b3e6411)
  • Improve and refactor basic fixture (#​35687)
  • Slim down client-only, chunk-error and axis-independent suites (#​35706)
  • Do not run type checking when benchmarking nuxt build (6355f3bc9)
  • kit: Scope loadNuxt temp dir so it doesn't delete sibling fixtures (37301dd51)
  • Guard against transient undefined _route in gotoPath (ca92d082b)
  • Retry fixture prepare on transient ENOTEMPTY (3a6b59f96)
  • Raise route-HMR polling timeout to reduce e2e flakiness (01dc27b7e)
  • Update bundle size snapshot (30d24817c)
🤖 CI
  • Rebalance shards and drop non-vite windows fixtures (#​35700)
  • Warm windows dependency cache on main (#​35730)
  • Run knip in default and production modes (#​35745)
  • Run knip on pull requests (d620aa972)
  • Prepare tests (c7bf7f738)
  • Also prepare tests in knip job (58f68bd64)
  • Check internal docs links on pull requests and all links weekly (#​35767)
❤️ Contributors

v4.5.0

Compare Source

4.5.0 is the next minor release.

📣 Some News

Preparing for Nuxt 5

A good chunk of this release is (hopefully) invisible plumbing for Nuxt 5. We've moved onto the latest major versions of several core dependencies (unhead v3, unctx v3, and Vite 8), switched the framework's own build over to tsdown, and introduced a stable nuxt/* build output contract with dev exports so that type-checking in the Nuxt monorepo works without a build step (#​35463, #​35605).

Much of this is working to shrink the gap between v4 and v5 internally, so that the migration will be as boring as possible.

[!TIP]
If you want to test some of the breaking changes of Nuxt v5, you can already opt in with future.compatibilityVersion: 5. Keep an eye on the Upgrade Guide for details as they land.

With the release of Nuxt v4.5, our focus as a team will turn to stabilising Nuxt v5 and creating compatibility utilities to make the upgrade as smooth as possible.

Nuxt 3 End-of-Life

Nuxt 3 reaches end-of-life on July 31, 2026, so this is one of the last few 3.x releases we'll ship. If you're still on v3, now is a great time to move across. Most people told us the v3 to v4 upgrade was smooth, and we've kept the upgrade guide up to date.

Alongside v4.5.0 we're publishing a maintenance patch for the 3.x line (v3.21.9) with the compatible bug fixes and smaller improvements from this release backported. The headline items here (Vite 8, Rspack 2, unhead v3, unctx v3) are major upgrades and stay v4-only, so 3.x remains stable as it approaches end-of-life.

👀 Highlights

Nuxt 4.5 is a big one. This release ships three major upgrades to the build layer (Vite 8, Rspack 2, and a brand new Rsbuild-powered pipeline for the Rspack builder), an experimental SSR streaming mode, a handful of new composables and conventions, and a lot of groundwork that brings us closer to Nuxt 5.

There's a lot here, so grab a coffee. ☕️

⚡️ Vite 8

Nuxt now runs on Vite 8 (#​34256). This brings faster cold starts, the latest Rolldown-powered internals, and many upstream improvements from the Vite team.

For most apps this is a transparent upgrade. If you have custom Vite plugins or config, it's worth skimming the Vite migration guide to check for anything that affects you.

[!WARNING]
Vite 8 is a major version bump. If you depend on Vite directly (custom plugins, vite.config tweaks, or ecosystem plugins that pin a Vite version), make sure those are compatible before upgrading in production.

🦀 Rspack 2 and Rsbuild

If you use the Rspack builder, this release is a substantial upgrade. We've moved to Rspack 2 (#​34929), which is faster and lighter, and rebuilt the builder on top of @rsbuild/core (#​35489).

The public surface stays the same. You still opt in with builder: 'rspack' and the existing rspack:* hooks continue to work:

// nuxt.config.ts
export default defineNuxtConfig({
  builder: 'rspack',
})

Under the hood, though, a lot has changed for the better:

  • The dev server now runs in middleware mode via Rsbuild, replacing webpack-dev-middleware and webpack-hot-middleware (#​35575).
  • We use an Rspack-specific Vue loader for correct SSR scoped-style ids and stricter ESM resolution (#​35566).

[!NOTE]
This is the foundation for first-class Rsbuild support. We kept the builder named rspack for now so nothing breaks, but the internals are now Rsbuild all the way down.

🌊 Experimental SSR Streaming

This is one I'm particularly excited about. You can now enable SSR streaming to dramatically improve Time to First Byte (#​34411). Instead of buffering the whole rendered page and sending it in one go, Nuxt flushes the HTML shell (your <head>, styles, preload hints, and entry scripts) immediately, then streams the body as Vue renders it.

// nuxt.config.ts
export default defineNuxtConfig({
  experimental: {
    ssrStreaming: true,
  },
})

Streaming is automatically disabled for bots and crawlers so search engines still receive fully-rendered HTML. You can tune which user agents count as crawlers, and you can opt individual routes out:

// nuxt.config.ts
export default defineNuxtConfig({
  experimental: {
    ssrStreaming: {
      botRegex: /googlebot|bingbot|my-internal-crawler/i,
    },
  },
  routeRules: {
    '/no-stream/**': { streaming: false },
  },
})

There's one thing worth understanding before you turn it on. Because streaming commits the HTTP status and headers with the very first byte, anything that mutates the response after rendering has begun (a setResponseStatus() in a <script setup>, a cookie write during middleware, and so on) can't reach the client. Nuxt handles the common cases for you: routes with redirect, cache, isr, swr, noScripts, or ssr: false rules automatically fall back to the buffered renderer, and in development we log a warning naming any dropped mutations so nothing fails silently.

[!WARNING]
SSR streaming is experimental and off by default. It could be great for content-heavy routes where TTFB matters, but test it against your app's response-mutating logic (status codes, headers, cookies) before shipping it widely. The experimental features docs cover the fallback rules and caveats in detail.

📖 SSR streaming documentation

🩺 Stable Error Codes

This one I'm really happy about. Nuxt now has a stable error code system (#​35429). Warnings and errors raised during build and at runtime now carry a stable code (like NUXT_E1001 or NUXT_B5001), a short explanation of why it happened, and a concrete fix to try.

Every code is greppable and bookmarkable, and the ones that need more than a one-line fix link straight to a dedicated docs page. For example, the classic "a composable was called outside a Nuxt context" now surfaces as NUXT_E1001 with the why/fix inline and a docs page explaining the context rules and how to use runWithContext().

To keep production output lean, the verbose why/fix text is stripped from production builds, leaving just the stable code.

This is the foundation for much better error messages across Nuxt, and we'll keep migrating existing warnings and errors onto it over the coming releases. If you've ever squinted at a cryptic Nuxt message, this is for you.

🎨 useLayout Composable

There's a new useLayout composable for reading the layout that's been resolved for the current route (#​35623). Previously there was no clean, reactive way to ask "which layout is this page using?" from within a component.

<!-- app/components/LayoutBadge.vue -->
<script setup lang="ts">
const layout = useLayout()
</script>

<template>
  <span>Current layout: {{ layout }}</span>
</template>

It returns a read-only computed ref, so it stays in sync as you navigate or as route rules and definePageMeta change the resolved layout.

📖 useLayout documentation

🪟 Named Views

Nuxt now supports named views through a filename convention (#​35123). If a parent page renders more than one <NuxtPage> outlet, you can give each outlet a name and provide a sibling page file for it using the name@view.vue convention:

# Directory Structure
-| pages/
---| parent/
-----| child.vue
-----| child@sidebar.vue
---| parent.vue
<!-- pages/parent.vue -->
<template>
  <div>
    <NuxtPage />
    <aside>
      <NuxtPage name="sidebar" />
    </aside>
  </div>
</template>

Navigating to /parent/child renders child.vue into the default outlet and child@sidebar.vue into the sidebar outlet. This has actually been possible in Vue Router for a long time; this release wires it up to Nuxt's file-based routing.

[!NOTE]
definePageMeta is read from the default route file only, and per-view rendering modes aren't supported (the parent page's mode applies to the default view).

📖 Named views documentation

🚦 enabled Option for useFetch and useAsyncData

You can now gate data fetching with a reactive enabled option (#​33260). While enabled is false, every execution is blocked (the initial fetch, execute/refresh, and watch triggers), and if you flip it from true to false mid-flight, the in-flight request is cancelled without clearing your existing data.

<script setup lang="ts">
const query = ref('')

const { data } = await useFetch('/api/search', {
  query: { q: query },
  // Only fetch once the user has typed something
  enabled: () => query.value.length > 2,
})
</script>

This is perfect for dependent or conditional queries, where you don't want to fire a request until some precondition is met. It pairs naturally with a getter or a ref, so it stays reactive.

📖 useAsyncData documentation

🔗 NuxtLink Prefetch Control for Custom Slots

When you use <NuxtLink> with the custom prop, Nuxt no longer attaches prefetch handlers for you, because it can't know how you've structured your markup. To make that ergonomic, the slot now exposes everything you need to wire prefetching up yourself (#​34539):

<template>
  <NuxtLink
    v-slot="{ href, navigate, prefetch, prefetched, shouldPrefetch }"
    to="/about"
    custom
  >
    <a
      :href="href"
      :class="{ 'is-prefetched': prefetched }"
      @click="navigate"
      @pointerenter="shouldPrefetch('interaction') && prefetch()"
      @focus="shouldPrefetch('interaction') && prefetch()"
    >
      About page
    </a>
  </NuxtLink>
</template>

You get prefetch to trigger it, prefetched to know whether it's already happened (great for a prefetched class), and shouldPrefetch to respect the user's connection and config.

📖 NuxtLink documentation

⚡️ Forwarded Preload Hints on Prefetch

Here's another one we'd love you to try. When you prefetch a link to a route with payload extraction, Nuxt already primes the destination's data and chunks. With the new opt-in experimental.prefetchPreloadTags (#​35144), it also forwards the destination's <link rel="preload"> and modulepreload hints (whatever the page sets 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 resources the user is looking at right now.

// nuxt.config.ts
export default defineNuxtConfig({
  experimental: {
    prefetchPreloadTags: true,
  },
})

The practical effect is that heavy above-the-fold assets on the next page (a hero image, a critical script) start downloading while the user is still on the current one, so the navigation feels instant. It's off by default while we gather feedback, so please give it a spin and tell us how it behaves on your app.

🌐 import.meta.envName

The resolved Nuxt environment name is now available at runtime as import.meta.envName for both Vite and webpack/Rspack builds (#​34844). This is the value set by --envName (or the resolved default), so you can branch on it in your app code:

if (import.meta.envName === 'staging') {
  // enable staging-only behaviour
}

📖 import.meta documentation

🔭 Tracing Channels for SSR Events

Nuxt now publishes diagnostics-channel traces for its server-side subsystems (#​35191). It's unopinionated: we emit nuxt.render, nuxt.island, nuxt.data, and nuxt.plugin channels following the untracing naming convention, and you can build OpenTelemetry (or anything else) on top. It works in Node, Deno, Bun, and Cloudflare Workers.

// nuxt.config.ts
export default defineNuxtConfig({
  // Turn on Nuxt's own channels
  tracingChannel: true,
})

You can also enable it granularly. In Nuxt v5, there will be additional Nitro-level channels:

// nuxt.config.ts
export default defineNuxtConfig({
  tracingChannel: {
    nuxt: true,
  },
})

[!NOTE]
Channel names, payload shapes, and option keys may still change while the untracing registry settles.

📦 Dependency Upgrades
unhead v3

Nuxt's head management now runs on unhead v3 (#​34793). It's smaller, uses a synchronous engine internally, and ships better type-safety for useHead out of the box. This also unblocks SSR streaming.

[!WARNING]
unhead v3 introduces type-narrowing for useHead, which can be a breaking type change if you were relying on the looser v2 types. The runtime behaviour is compatible for the vast majority of apps, and promise input (deprecated in v2) is no longer supported. If you hit type errors after upgrading, they're almost always genuine tightening rather than regressions.

unctx v3

We've moved to unctx v3 (#​35541), which resolves a class of long-standing async context issues (#​33644). This is part of the composable-context reliability work that continues into v5.

And more

We've also updated magic-string to v1, Babel to v8, and pulled in the latest Rolldown across the board. Running nuxt upgrade --dedupe (see below) is the easiest way to pull these through cleanly.

🛠️ Nuxt CLI

This release bundles some improvements from @nuxt/cli v3.36 and v3.37:

  • nuxt module remove to uninstall a module and clean up its config (nuxt/cli#1306), the natural companion to nuxt module add.

  • Non-interactive nuxt init for scripting and CI ([nuxt/cli#

Note

PR body was truncated to here.


Configuration

📅 Schedule: (UTC)

  • Branch creation
    • At any time (no schedule defined)
  • Automerge
    • At any time (no schedule defined)

🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about these updates again.


  • If you want to rebase/retry this PR, check this box

This PR was generated by Mend Renovate. View the repository job log.

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 16, 2025

Copy link
Copy Markdown

Deploying dev-mode with  Cloudflare Pages  Cloudflare Pages

Latest commit: 35467c8
Status:🚫  Build failed.

View logs

@renovate
renovate Bot force-pushed the renovate/major-nuxt branch 2 times, most recently from a516d71 to 03d6944 Compare July 28, 2025 08:08
@renovate
renovate Bot force-pushed the renovate/major-nuxt branch from 03d6944 to 043f8ab Compare July 29, 2025 04:25
@renovate
renovate Bot force-pushed the renovate/major-nuxt branch 3 times, most recently from 0413f39 to 42aa1a3 Compare August 11, 2025 08:55
@renovate
renovate Bot force-pushed the renovate/major-nuxt branch 2 times, most recently from d14141f to 9513d99 Compare August 19, 2025 13:51
@renovate
renovate Bot force-pushed the renovate/major-nuxt branch 2 times, most recently from ce030d2 to 7c50a1a Compare August 31, 2025 10:35
@renovate
renovate Bot force-pushed the renovate/major-nuxt branch 3 times, most recently from 5a12d1a to f40a8fc Compare September 8, 2025 04:30
@renovate
renovate Bot force-pushed the renovate/major-nuxt branch 2 times, most recently from 1d2d0e9 to 608cdb9 Compare September 16, 2025 21:09
@renovate
renovate Bot force-pushed the renovate/major-nuxt branch from 608cdb9 to e9f6402 Compare September 25, 2025 18:10
@renovate
renovate Bot force-pushed the renovate/major-nuxt branch from e9f6402 to 8820652 Compare October 6, 2025 18:55
@renovate
renovate Bot force-pushed the renovate/major-nuxt branch 2 times, most recently from 1fc5358 to d6a86b0 Compare October 25, 2025 06:13
@renovate
renovate Bot force-pushed the renovate/major-nuxt branch 2 times, most recently from fed7e09 to 60d9c3d Compare November 10, 2025 15:29
@renovate
renovate Bot force-pushed the renovate/major-nuxt branch from 60d9c3d to ca48e08 Compare November 16, 2025 13:26
@socket-security

socket-security Bot commented Nov 16, 2025

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Updated@​nuxt/​test-utils@​3.21.0 ⏵ 4.1.09710079 +290 +4100
Updatedvue@​3.5.25 ⏵ 3.5.41100 +110091 -197100

View full report

@renovate
renovate Bot force-pushed the renovate/major-nuxt branch 2 times, most recently from 4add32c to 68d6b72 Compare November 16, 2025 17:32
@renovate
renovate Bot force-pushed the renovate/major-nuxt branch 3 times, most recently from 4950264 to 9ea0fc7 Compare November 24, 2025 10:06
@renovate
renovate Bot force-pushed the renovate/major-nuxt branch 2 times, most recently from 0d642a0 to ec8ff5a Compare December 9, 2025 19:36
@renovate
renovate Bot force-pushed the renovate/major-nuxt branch 2 times, most recently from 5028f29 to 87d6018 Compare December 15, 2025 13:25
@renovate
renovate Bot force-pushed the renovate/major-nuxt branch 3 times, most recently from a48d296 to 3177aed Compare January 23, 2026 18:28
@renovate
renovate Bot force-pushed the renovate/major-nuxt branch 2 times, most recently from 3b336d8 to 3ac2a00 Compare February 7, 2026 12:55
@renovate renovate Bot changed the title chore(deps): update dependency nuxt to v4 chore(deps): update nuxt core to v4 (major) Feb 7, 2026
@renovate
renovate Bot force-pushed the renovate/major-nuxt branch from 35467c8 to 1191dfc Compare August 6, 2026 08:43
@renovate renovate Bot changed the title chore(deps): update nuxt core to v4 (major) chore(deps): update nuxt core to v4 Aug 6, 2026
@renovate

renovate Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor Author

Edited/Blocked Notification

Renovate will not automatically rebase this PR, because it does not recognize the last commit author and assumes somebody else may have edited the PR.

You can manually request rebase by checking the rebase/retry box above.

⚠️ Warning: custom changes will be lost.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants