👀 Highlights
🐣 A New CLI
We've refactored nuxi
using unjs/citty and this marks the first Nuxt release that depends on the new version, safely in its own repository. We have grand plans for this - check out some of the features + roadmap discussions in nuxt/cli and please feel free to contribute!
Nuxi is now decoupled from the main nuxt
version - we plan to iterate and release nuxi more quickly in future so you can expect new things coming soon!
🕸️ Native Web Streams and Response
With improvements in unjs/h3 and unjs/nitro, it's now possible to directly return a Response
object from server routes, meaning it's also possible to return and handle streams natively in Nuxt.
👉 Check out the full detail in the unjs/h3 and unjs/nitro release notes.
🔥 HTML Rendering Optimisations
This release comes with a couple of improvements in rendering HTML responses from the server. We now determine whether to preload/prefetch resources at build time (so you can customise this in the build:manifest
hook). We also now manage rendering the HTML for them directly in unhead
(#22179), which means you can configure the order for <link>
, <meta>
, <script>
, <style>
, and more. And - in our preliminary testing - it's even faster!
It's possible to opt-in to upcoming head improvements with the experimental.headNext
flag. This currently includes a new ordering algorithm based on capo.js (#22431) and allows enabling future optimisations as they are released in unhead
:
export default defineNuxtConfig({
experimental: {
headNext: true
}
})
We'd love your thoughts - you can respond with any issues/feedback in this discussion.
🛠️ Build Environment Shortcuts
In your Nuxt config you can now use $client
and $server
shortcuts to easily define configuration that is specific to just the Vite client/server (#22302) or webpack client/server (#22304) builds. This previously was only possible with the vite:extendConfig
and webpack:config
hooks.
For example:
export default defineNuxtConfig({
vite: {
$client: {
build: {
rollupOptions: {
output: {
chunkFileNames: '_nuxt/[hash].js',
assetFileNames: '_nuxt/[hash][extname]',
entryFileNames: '_nuxt/[hash].js'
}
}
}
}
}
})
⚡️ Vite 4.4
We've chosen to unpin Vite from minor versions, meaning whenever Vite releases a new feature version you can opt-in straight away. Vite 4.4 brings a lot of exciting things, including experimental Lightning CSS support - and much more!
👉 Check out the Vite release notes for more.
💪 TypeScript Updates
We now use purely relative paths in the generated tsconfig.json
instead of setting a baseUrl
. This means better support for dev environments like docker images where the absolute path may not match your IDE (#22410).
We also set a couple of additional compiler flag defaults to match Vite/TS recommendations (#22468).
Plus, you should now get type hinted access to layouts in setPageLayout
and also in <NuxtLayout name>
(#22363).
🦄 Async Context support
If you've ever got an issue with 'Nuxt context unavailable' this might be one for you. We now support native async context for Bun and Node under an experimental flag, in both Nuxt and Nitro (#20918).
This enables using Nuxt composables on the server without needing to ensure they are being called directly in a setup function. It also allows the same in Nitro, with a new useEvent()
utility that is usable in server routes.
To try it out, you can enable experimental.asyncContext
:
export default defineNuxtConfig({
experimental: {
asyncContext: true
}
})
👓 Watcher Updates
We've fixed a couple of issues with watchers, meaning that you should need to restart your server less often - and you should see a significant performance increase if you are using layers.
⚗️ Nitro 2.6
There lots more exciting features coming directly from Nitro 2.6, including smaller, lighter servers and new persistent data storage in a .data
directory.
👉 Read more in the full release article.
✅ Upgrading
As usual, our recommendation for upgrading is to run:
npx nuxi upgrade --force
This will refresh your lockfile as well, and ensures that you pull in updates from other dependencies that Nuxt relies on, particularly in the unjs ecosystem.
👉 Changelog
🚀 Enhancements
- vite: Unpin vite from minor (#22031)
- nuxt: Polyfill idle callback utils (#21863)
- nuxt: Smooth scroll behavior option (#21948)
- schema,vite: Allow
$client
and$server
vite env overrides (#22302) - schema,webpack: Allow
$client
and$server
overrides (#22304) - nuxt: Allow dynamic
scrollToTop
page meta (#21741) - nuxt: Expose filtered templates in
app:templatesGenerated
hook (#21935) - nuxt: Render all head tags on server with
unhead
(#22179) - nuxt: Auto-install
@nuxt/webpack-builder
when needed (#21747) - nuxt: Allow remote sources for islands (#21592)
- nuxt: Environment-specific plugin execution for islands (#20726)
- kit,nuxi: Add
writeTypes
utility (#22385) - nuxt: Autocomplete layouts in
setPageLayout
/<NuxtLayout>
(#22362) - nuxt: Allow 'lazy' (non-blocking) server components (#21918)
- nuxt: Use build plugin to access nuxt route injection (#21585)
- vite,webpack: Tree-shakable
import.meta.*
build flags (#22428) - nuxt: Resolve unresolved paths within
node_modules
(#22478) - nuxt: Experimental native async context support (#20918)
- nuxt: Warn on external
webpack
/nitro
/postcss
config (#22521) - nuxt: Allow experimental
global: 'sync'
components (#22558) - nuxt: Make
app.rootId
optional (#22528) - nuxt: Add
experimental.headNext
unhead integration (#22620) - cli: Detect
bun
package manager (#22673) - nuxt: Upgrade nitro + reduce node-specific usage (#22515)
- nuxt: Add support for
routeRules
defined within pages (#20391) - schema: Support setting
hidden
sourcemaps (#22787) - kit,nuxt: Respect nuxt ignore patterns in nitro (#22808)
- nuxt: Migrate to new
nuxt/cli
(#22799) - schema: Export
./schema/config.schema.json
subpath (#22813)
🔥 Performance
- nuxt: Export DefineNuxtConfig interface from
nuxt/config
(#22391) - nuxt: Write templates in single sync step + improve logs (#22384)
- nuxt: Render css/inline css higher than resource hints (#21793)
- nuxt: Experimental support of
capo.js
head tag order (#22431) - nuxt: Use LRU prerender cache and limit cached items (#22465)
- nuxt: Reduce multiple calls to
.toLowerCase()
(#22743) - nuxt: Reduce multiple calls to dirname (#22800)
🩹 Fixes
- nuxt: Await
prerender:routes
hook (#22247) - nuxt: Access resolved
scrollBehaviorType
(#22264) - nuxt: Add overloads for
asyncData
generic + default (#22258) - nuxt: Bind
createClientOnly
render function to ctx (#22289) - webpack: Remove legacy support for
build.extend
(#22305) - nuxt: Allow
validate
return typing to be either error or boolean (#22323) - kit: Handle tuple-format modules in
hasNuxtModule
(#22316) - nuxt: Components auto-import for JSX (#22330)
- nuxt: Pass (and handle) relative paths in
builder:watch
(#22333) - nuxt: Use computed path value for
useFetch
hash (#22378) - cli: Only strip extensions from files (#22399)
- nuxt: Disallow redirects to more script protocols (#22366)
- nuxt: Test
watch
paths against all layersrcDir
s (#22307) - nuxt:
name
is an optional prop for<NuxtLayout>
(0d9a0b753) - kit: Don't unsubscribe from file writing (716a5b834)
- nuxt: Support uppercase route methods in
useFetch
(#22418) - kit: Remove
baseUrl
and use relative paths in tsconfig (#22410) - nuxt: Print name of missing island component (#22440)
- nuxt: Broken capo.js
injectHead
usage (#22447) - kit: Apply preferred options for esbuild transpilation (#22468)
- nuxt: Correctly update object cookies in
useCookie
(#22474) - nuxt: Use
internal:nuxt
namespace (9b0d371b0) - nuxt: Remove unused
normalize
call (14bf2b02f) - cli: Display log when restarting nuxt (#22500)
- nuxt: Resolve type import paths (#22476)
- schema:
webpack
options should be optional (#22524) - nuxt: Enable hmr of
app.config.ts
files (#22494) - vite: Add
hookable
to externals list (4552d39c4) - vite: Disable assignement in replace plugin (37ba58630)
- schema: Ignore empty string in
app.{rootId ([rootTag}
(#22543)](rootTag}` (#22543))) - vite: Include
import.meta
build vars indefine
as well (#22576) - nuxt: Provide fallback route (#22580)
- nuxt: Trigger immediate DOM update on
page:finish
(#22566) - nuxt: Unsub from hooks when unmounting indicator (#22592)
- cli: Only watch
distDir
after first build (#22614) - nuxt: Use relative paths when augmenting types (#22633)
- nuxt: Don't prompt to install packages in CI (#22636)
- cli: Ignore error if nitro is not enabled on bridge (#22642)
- nuxt: Remove experimental hash hydration (#22648)
- nuxt: Correct revive payload data type (#22667)
- vite: Use
''
key for root scope in variable collector (#22679) - nuxt: Warn when ignoring duplicate island/server component (#22709)
- nuxt: Add
exclude
paths to nitrotsconfig.server.json
(#22768) - nuxt: Recreate
asyncData
whenimmediate
is disabled (#20980) - nuxt: Respect ignorelist when scanning auto-imports (#22782)
- schema: Mark schema as free of side effects (#22793)
- nuxt: Default
spaLoadingTemplate
tofalse
(#22798) - nuxt: Fully resolve
unctx
where possible (#22811) - vite: Only mark nitro deps as externals when building (#22812)
💅 Refactors
- nuxi,schema: Move loading template into schema (#22336)
- nuxt: Add additional flag to enable remote sources (#22409)
- nuxt: Use
nuxi-ng
for edge releases (#22413) - nuxt: Import
useNitroApp
from subpath (#22785)
📖 Documentation
- Mention
#components
import for dynamic component (#22231) - Fix typo (#22308)
- Add information on how to type custom hooks (#22312)
- Correct manually typing runtime config example (#22393)
- Update
.env
section (#22369) - Add example for accessing vite config programmatically (#18812)
- Add recommendation to install nuxtr (#20808)
- Add some more debugging tips (#22415)
- Document
NuxtIsland
(#22434) - Escape
]
in code-block filenames (#22389) - Add temporary website for docs contribution (#22469)
- Update prerender documentation (#22471)
- Update hybrid rendering section (#22475)
- Fix typo in
scrollToTop
(#22503) - Add
status
type foruseAsyncData
(#22511) - Rephrase link to
useSeoMeta
parameters (#22513) - Update api example for
pick
(#22531) - Add closing blocks for
ReadMore
components (#22541) - Update rendering error page (#22523)
- Mention adding auto-import of third party packages (#22575)
- Update and shorten server example (#22583)
- Update twitter/X logo (#22569)
- Added
addServerHandler
example to modules author guide (#22603) - Clarify
server: false
doesn't await on initial load (#22619) - Fix link to deployment page (#22618)
- Warn directives must be registered on both server/client (#22627)
- Revert
import.meta.*
update until v3.7 release (98c17e5d4) - Improve custom component dirs example (#22697)
- Mention
NuxtIsland
in server only components docs (#22685) - Add additional type generics to
useFetch
docs (#22755) - Add additional type generics to
useAsyncData
(#22760) - Add instructions for Bun package manager (#22779)
- Fix typo in bun package manager name (#22781)
📦 Build
- Skip releasing
nuxi
(df2bc8a72)
🏡 Chore
- Dedupe and bump semver (#22322)
- Update codesandbox links (5edf00f06)
- Add issue reproduction bot (#22495)
- Remove unused import (8eefb6548)
- Increase stale operations per run (#22501)
- Refresh lockfile (#22518)
- Increase stale bot limit to 300 (#22538)
- schema: Enable linting (#22546)
- Replace
.eslintignore
file with 'ignorePatterns' (#22547) - kit: Remove unused internals (#22555)
- Depend on
h3-nightly
on edge releases (#22593) - Check if deps exist (817c12f02)
✅ Tests
- Remove separate test for baseurl (#22467)
- Remove JS payload test + add non-async context test (#22530)
- Refactor test suite and reduce
networkidle
dependency (#22596) - Reduce verbose log outputs (c8cba7a06)
- Add regression test for escaping payload (#22774)
🤖 CI
- Add ecosystem-ci pr comment trigger (#22239)
- Add semantic pull request workflow (#22241)
- Grant permission to comment on prs (6f1a557e5)
- Harden GitHub actions (#22321)
- Pin actionlint script (#22324)
- Skip semantic validation on release branches (459dc7d2d)
- Update issue label for reproduire (4e0a499a0)
- Pin version of actionlint used (b702adc24)
- Try another way to disable semantic validation of release prs (eff05e1d4)
- Bump timeout minutes for windows fixtures 🙈 (33389dc4e)
❤️ Contributors
- Pooya Parsa (@pi0)
- Daniel Roe (@danielroe)
- Mihailo Bursac (@djixadin)
- Jongmin Yoon (@jongmin4943)
- Muhammad Mahmoud (@MuhammadM1998)
- Colin McDonnell (@colinhacks)
- Xxxhussein (@xxxhussein)
- Julien Huang (@huang-julien)
- Jabin (@@JabinPeng)
- Eternalltruth (@eternalltruth)
- JD Solanki (@jd-solanki)
- Anhao (@ah-dc)
- Eduardo San Martin Morote (@posva)
- Harlan Wilton (@harlan-zw)
- Fares Djefaflia (@frs99)
- Michael (@nihul87)
- Ryota Watanabe (@wattanx)
- Damian Głowala (@DamianGlowala)
- Sam K (@samk-dev)
- Adityawarman Dewa Putra (@devdewa)
- beer (@iiio2)
- Alexander Lichter (@manniL)
- Damian Głowala (@DamianGlowala)
- Heb (@Hebilicious)
- Curt Grimes (@curtgrimes)
- Lehoczky Zoltán (@Lehoczky)
- Jonas Thelemann (@dargmuesli)
- Lucas Vargas (@vargasmesh)
- Andrey Yolkin (@AndreyYolkin)
- Peter Graugaard (@pgraug)
- Josh Deltener (@hecktarzuli)
- Estéban (@Barbapapazes)
- Sébastien Chopin (@Atinux)
- Nobkd (@nobkd)
- MiniDigger (@MiniDigger)
- David Marr (@marr)
- Adham Farrag (@adhamfarrag)
- Jean-Pierre Carvalho (@jeanpierrecarvalho)
- Joaquín Sánchez (@userquin)
- Anthony Fu (@antfu)
- Prashant Palikhe (@prashantpalikhe)
- Ted Xu (@xuzuodong)
- Aleksandra (@beerose)
- Dawid Kopys (@DawidKopys)
- OhB00 (@OhB00)
- Sisir Ghimire Chettri (@tuxsisir)
- Maik Kowol (@94726)
- Rudolf Byker (@rudolfbyker)
- Bogdan Kostyuk (@logotip4ik)