4.0.0-alpha.1 is the first alpha release of Nuxt 4 for early testing
We originally planned Nuxt 4 for June 2024, but things don't always go according to plan. I think it's appropriate to take a different approach:
👉 Nuxt 4 alpha will ship June 2, 2025, with a stable release at the end of the month. Nuxt 5 will come later once Nitro v3 is ready.
...
Today we release Nuxt v4 alpha 1! We'd love early adopters to test it. Please do report issues to Nuxt or any modules that you may be using.
Important
At the alpha stage, we are still planning additional breaking changes (and expect there will be bugs or 'friction'); at the beta stage, we are not planning breaking changes but they may occur if necessary. At the release candidate stage we expect only bug fixes.
Here's what you can expect over the next few weeks:
- We plan to open upstream PRs for community modules in the nuxt/modules registry, and create a migration guide for module authors.
- We'll create a full upgrade guide for Nuxt 3 users, including a list of breaking changes and how to migrate. (The current upgrade guide explains how to enable compatibility mode, but there are some differences with Nuxt 4.)
- We'll only release bugfixes for v3 this month, deferring backporting new features until after the release of v4.
- We'll update the docs on nuxt.com to allow switching between
3.x,4.xand (soon)5.xdocumentation. - Once we release the release candidate (we're aiming for June 23) we'd love everyone to dive in again for a last round of testing. We'll only be expecting bugfixes from this point onward.
- Once v4 is released, we'll separate the
mainbranch to4.xto adopt edge releases ofh3andnitroand begin development of Nuxt 5.
Tip
You can follow the progress of the remaining work by checking these remaining tasks and the Nuxt 4 milestone on GitHub.
I'm really excited with this timeline — and thank you for your patience and trust over the last year!
👉 Read more at https://nuxt.com/blog/roadmap-v4
🚀 Enhancements
- kit,nuxt,schema,vite,webpack: Nitropack v3 nightly (#27702)
- ui-templates: Update template branding for v4 (#27843)
- deps: Upgrade to latest versions of c12, jiti and unbuild (#27995)
- kit: Reimplement cjs utils using
mlly(#28012) - nuxt: Generate basic jsdoc for module config entry (#27689)
- schema: Split dev/prod build directories (#28594)
- nuxt: Cache vue app build outputs (#28726)
- deps: Update dependency vite to v6 (main) (#30042)
- nuxt: Add integration with chrome devtools workspaces (#32084)
🔥 Performance
- nuxt: ⚠️ Don't call
render:htmlfor server islands (#27889) - vite: Don't write stub manifest for legacy bundler (#27957)
- kit: Update env expansion regex to match nitro (#30766)
- nuxt: Replace remaining instance of
globby(#31688)
🩹 Fixes
- schema,vite: ⚠️ Do not allow configuring vite dev bundler (#27707)
- schema: ⚠️ Default to
compatibilityVersion: 4(#27710) - nuxt: ⚠️ Emit absolute paths in
builder:watchhook (#27709) - nuxt: ⚠️ Improve default
asyncDatavalue behaviour (#27718) - nuxt: ⚠️ Remove old experimental options (#27749)
- kit: ⚠️ Support loading nuxt 4 and drop support for <=2 (#27837)
- nuxt: ⚠️ Remove
__NUXT__after hydration (#27745) - ui-templates: Add default title back (3415241a6)
- kit: ⚠️ Drop support for building nuxt 2 projects (1beddba6a)
- nuxt: ⚠️ Bump internal majorVersion to
4(7aae4033b) - kit: Mark
resolvePathutils as sync (655e1473d) - kit: Revert change to
tryResolveModule(2d136e04c) - kit: Add back
requireModuleandtryRequireModule(#28013) - nuxt: Hide unhandled error messages in prod (#28156)
- nuxt: Add
useScriptCrispscripts stub (0c3cc4cf3) - nuxt: ⚠️ Remove unused
globalNameproperty (#28391) - nuxt: Use static import for
updateAppConfigin HMR (#28349) - vite: Write dev manifest when
ssr: false(#28488) - kit,nuxt,schema: ⚠️ Remove other support for nuxt2/bridge (#28936)
- webpack: Only insert dynamic require plugin when building (b619b35e9)
- nuxt: Guard
windowaccess (d874726ff) - nuxt: Remove unneeded subpath import (18a6ef1ca)
- webpack: Handle new webpack chunk format (d293c06d2)
- nuxt: Wrap slot with
h()in ClientOnly (#30664) - kit: ⚠️ Do not check compatibility for nuxt version < 2.13 (f94cda4c8)
- ui-templates: Fix examples link and add bluesky (#30866)
- vite: Use
resolveIdfromvite-nodeto resolve deps (#30922) - nuxt: Import
isEqualfrom mainohashexport (3ec1a1e5e) - vite: Don't set
output.preserveModules(ce49734aa) - nuxt: Ignore
#app-manifestimport in dev mode (#31539) - nuxt: Ensure layer array-type config is merged in order (#31507)
- schema: Turn off
purgeCachedDatauntil v4 (7aa3a01ae) - schema: Re-enable
purgeCachedDataby default (06745604c) - webpack: Expand dynamic require regexp to match new pattern (62e700daa)
- nuxt: Add back missing reset of
.execute(d79e14612) - nuxt: Remove unneeded pattern from regexp (cf4598d0d)
- nuxt: Ensure
appConfigsources are not duplicated (#32216) - nuxt,schema: ⚠️ Remove support for
compatibilityVersion: 3(#32255) - nuxt: Access
asyncDatastate from nuxt app instance (#32232) - kit,nuxt,schema,vite: ⚠️ Remove support for some deprecated options (#32257)
- nuxt: Make patterns relative to
srcDirinbuildCache(#32260) - nuxt: ⚠️ Don't rerun asyncdata w/ existing data in
useAsyncData(#32170) - nuxt: Return non-existent route component in RouteProvider (#32266)
- nuxt: Scan nitro handlers before writing types (a3698c08b)
- nuxt: Force asyncData
errorValue/valueto be undefined (7e4eac655) - nuxt: ⚠️ Remove public and assets aliases (#32119)
- nuxt: Use single
asyncDatawatcher (#32247)
💅 Refactors
- kit,nuxt: ⚠️ Drop nuxt 2 + ejs template compile support (#27706)
- nuxt: ⚠️ Move
#app/components/layout->#app/components/nuxt-layout(209e81b60) - kit,nuxt,vite,webpack: ⚠️ Remove legacy require utils (#28008)
- nuxt: Simplify check of
dedupeoption (#28151) - nuxt: Use direct import of
installNuxtModule(501ccc375) - kit: Remove internal function (#32189)
- Downgrade to nitro v2 (#32252)
- schema: ⚠️ Remove config.schema.json export + defaults (#32254)
- nuxt: Migrate to
oxc-walker(#32250) - nuxt,schema: Use oxc for
onPrehydratetransform (#32045)
📖 Documentation
- Indicate what
useAsyncDatamust return (#28259) - Update
deepdefault foruseAsyncData&useFetch(#28564) - Add props to special metadata (#29708)
- Fix link to issue (4d13f1027)
- Fix typos (#30413)
- Update
addRouteMiddlewarepath in example (#32171) - Narrow link to just middleware (#32203)
- Use optional chaining in error example (#32214)
- Give example of using
--env-file(15fb7b30f) - Recommend
nuxtcommand consistently (#32237) - Improve wording for
deepoption (bec85dfcd) - Fix wrong
alertwithwarningin/guide/pages(#32270)
📦 Build
- deps: Bump esbuild from 0.23.1 to 0.25.0 (#31247)
🏡 Chore
- Manage update to
vite-plugin-checkerseparately (02d46dd3d) - Update docs typecheck command (#28433)
- Improve accuracy of 4.x changelog (#28706)
- Bump package versions internally to v4 (16fab7778)
- kit: Fix regressed version v4 (a1c052057)
- Dedupe lockfile (f14ef6bc9)
- Update once more (4d22f4d5a)
- Specify workspace
engines.nodecompatibility (a26322f5f) - Remove special treatment for typescript (08766a0cd)
- Reenable quarantine for webpack/memfs (for 3.x benefit) (9cb94e55e)
- Remove extra dep (f0ec34298)
- Add back
nuxi(9aa4c7c3b) - Remove stray
nuxiversion again (#30547) - Fix lockfile (7d345c714)
- Remove second version of vitest (#30868)
- Ignore
oxc-parserupdates temporarily (1cd0fb5cb) - Ignore
nitro/templatesdirectory (e531477f8) - Fix ui-templates build (c8a1b9e80)
- Mkdir for ui-templates (853408a1e)
- Add webpack resolution (088bcd459)
- Upgrade webpack dependencies separately (b6b66069d)
- Apply lint fixes (8f8db534a)
✅ Tests
- Remove unused experimental options (6d971ddc9)
- Add additional
attwtest for built packages (#30206) - Add minimal pages fixture (#30457)
- Update bundle size assertion (f458153d9)
- Update bundle size assertion (4cce6bf8d)
- Benchmark minimal fixture instead (#31174)
- Normalise scoped css + pass logger to
configResolved(8d3bd4f9f) - More precise asyncData tests (023fb13eb)
- Add regression test for useAsyncData + transition (8d65b941c)
- Ensure builder tests run sequentially (095f5716f)
🤖 CI
- Bump node v22 (#30251)
- Run workflows on merge groups (ff37ad9df)
- Do not invoke semantic-pr test on merge groups (fadd618d1)
⚠️ Breaking Changes
- nuxt: ⚠️ Don't call
render:htmlfor server islands (#27889) - schema,vite: ⚠️ Do not allow configuring vite dev bundler (#27707)
- schema: ⚠️ Default to
compatibilityVersion: 4(#27710) - nuxt: ⚠️ Emit absolute paths in
builder:watchhook (#27709) - nuxt: ⚠️ Improve default
asyncDatavalue behaviour (#27718) - nuxt: ⚠️ Remove old experimental options (#27749)
- kit: ⚠️ Support loading nuxt 4 and drop support for <=2 (#27837)
- nuxt: ⚠️ Remove
__NUXT__after hydration (#27745) - kit: ⚠️ Drop support for building nuxt 2 projects (1beddba6a)
- nuxt: ⚠️ Bump internal majorVersion to
4(7aae4033b) - nuxt: ⚠️ Remove unused
globalNameproperty (#28391) - kit,nuxt,schema: ⚠️ Remove other support for nuxt2/bridge (#28936)
- kit: ⚠️ Do not check compatibility for nuxt version < 2.13 (f94cda4c8)
- nuxt,schema: ⚠️ Remove support for
compatibilityVersion: 3(#32255) - kit,nuxt,schema,vite: ⚠️ Remove support for some deprecated options (#32257)
- nuxt: ⚠️ Don't rerun asyncdata w/ existing data in
useAsyncData(#32170) - nuxt: ⚠️ Remove public and assets aliases (#32119)
- kit,nuxt: ⚠️ Drop nuxt 2 + ejs template compile support (#27706)
- nuxt: ⚠️ Move
#app/components/layout->#app/components/nuxt-layout(209e81b60) - kit,nuxt,vite,webpack: ⚠️ Remove legacy require utils (#28008)
- schema: ⚠️ Remove config.schema.json export + defaults (#32254)
❤️ Contributors
- Alexander Lichter (@TheAlexLichter)
- Julien Huang (@huang-julien)
- Robin (@OrbisK)
- Matej Černý (@cernymatej)
- Daniel Roe (@danielroe)
- Hugo Richard (@HugoRCD)
- mxmxmmgg (@mxmxmmgg)
- Baptiste Leproux (@larbish)
- Phojie Rengel (@phojie)
- Michael Brevard (@GalacticHypernova)
- duolaameng (@1411430556)
- David Stack (@davidstackio)
- John Tanzer (@moshetanzer)
- @beer (@iiio2)
- हिमांशु (@CodeMan62)
- Norbiros (@Norbiros)
- watsonhaw5566 (@watsonhaw5566)
- xjccc (@xjccc)
- Ryota Watanabe (@wattanx)
- Max (@onmax)
- Alex Liu (@Mini-ghost)
- Martins Zeltins (@martinszeltins)
- Ivan Martianov (@ivansky)
- Lorenzo Fiamingo (@lorenzofiamingo)
- James (@Koshux)
- Pooya Parsa (@pi0)
- Kyohei Sonokawa (@kyohei-23)
- Saeid Zareie (@Saeid-Za)
- Bobbie Goede (@BobbieGoede)
- Damian Głowala (@DamianGlowala)
- Maxime Pauvert (@maximepvrt)
- Leonid (@john-psina)
- Wind (@productdevbook)
- Arkadiusz Sygulski (@Aareksio)
- Rohan Dhimal (@drowhannn)
- Daniel Kelly (@danielkellyio)
- Jeffrey van den Hondel (@jeffreyvdhondel)
- Sébastien Chopin (@atinux)
- Anthony Fu (@antfu)
- Yizack Rangel (@Yizack)
- Joaquín Sánchez (@userquin)
- IlyaL (@ilyaliao)
- Ben McCann (@benmccann)
- Alexandru Ungureanu (@unguul)
- Andrej Adamcik (@adamcikado)
- Dennis Adriaansen (@dennisadriaans)
- Guillaume Chau (@Akryum)
- 翠 / green (@sapphi-red)
- Johannes Buchholz (@jhony1104)
- Claudiu (@sofuxro)
- Anoesj Sadraee (@Anoesj)
- Peter Radko (@Gwynerva)
- Adam DeHaven (@adamdehaven)
- Francesco Agnoletto (@Kornil)
- imreegall (@imreegall)
- Sam Blowes (@blowsie)
- Nimit012 (@Nimit012)
- Camille Coutens (@Kamsou)
- Connor Pearson (@cjpearson)
- Connor Roberts (@murshex)
- Harlan Wilton (@harlan-zw)
- dependabot[bot] (@dependabot[bot])
- Kevin Deng 三咲智子 (@sxzz)
- Maik Kowol (@94726)
- Clayton Chew (@claytonchew)
- awfulness (@awfulness)
- Vahagn Zaqaryan (@Vahagn-Zaqaryan)
- Idorenyin Udoh (@idorenyinudoh)
- Jonas Thelemann (@dargmuesli)
- Horu (@HigherOrderLogic)
- Nolhan (@Nonolanlan1007)
- Typed SIGTERM (@typed-sigterm)
- Hans Tu (@ChiaHanTu)
- David Marr (@marr)
- Charlie ✨ (@CharleeWa)
- Hussain Panahy (@HP8585)
- Lansi (@lansi951)
- Yauheni Vasiukevich (@EvgenyWas)
- Alan Schio (@schirrel)
- Zakhar Shymanchyk (@zakshyman)
- Arturs Jansons (@iegik)
- Peter Buglavecz (@buglavecz)
- ikxin (@ikxin)
- Guspan Tanadi (@guspan-tanadi)
- Vuk Marjanovic (@vmrjnvc)
- Clément Ollivier (@clemcode)
- Anders Bootsmann Larsen (@bootsmann1995)
- Nishant Aanjaney Jalan (@cybercoder-naj)
- David Nahodyl (@Smef)
- derHodrig (@skoenfaelt)
- Matt (@matt-clegg)
- Nikolay (@RokeAlvo)
- bjoaquinc (@bjoaquinc)
- wzc520pyfm (@wzc520pyfm)
- Kraig Burrows (@zync09)
- Sébastien LeBlanc (@mrleblanc101)
- Teena (@franklin-tina)
- skmedix (@skmedix)
- Daniel Rentz (@danielrentz)
- Inesh Bose (@ineshbose)
- Felix Gabler (@felixgabler)
- mianlang (@mianlang)
- Tamás H. (@Tamas-hi)
- Farnabaz (@farnabaz)
- Jan-Niklas W. (@niklas-wortmann)
- Gustavo Aquino Torres Teixeira (@guska8)
- Stephanie Smith (@stephiescastle)
- crisarji (@crisarji)
- RBV1 (@RBV1)
- Adrien Foulon (@Tofandel)
- Efraim (@EfraimGENC)
- Aurion SARL (@TonyFresneau)
- Erik Lilja (@Lilja)
- Markus Oberlehner (@maoberlehner)
- Lukas Bauer (@luxterful)
- Till Sanders (@tillsanders)
- Nils (@BracketJohn)
- Estéban (@Barbapapazes)
- Cruz (@SparK-Cruz)
- Taras Batenkov (@enkot)
- Panopoulos Andreas (@b0ul17)
- Dawit (@oneminch)
- Ryoya (@harunari0928)
- Alexander (@hywax)
- Jelmer (@jelmerdemaat)
- Christoph Heike (@cheike569)
- Jeremy Graziani (@AcelisWeaven)
- Domenik Reitzner (@dreitzner)
- Jeel Rupapara (@zeelrupapara)
- Leopold Kristjansson (@leopoldkristjansson)
- Horváth Bálint (@horvbalint)
- Bochkarev Ivan (@Ibochkarev)
- Joschua (@selfire1)
- Indrek Ardel (@Ingramz)
- DarkVen0m (@DarkVen0m)
- Ezra Ashenafi (@Eazash)
- Artem Maslov (@Twocram)
- Paulo Ricardo Severo (@prsevero)
- Liran Tal (@lirantal)
- Osama Abdallah Essa Haikal (@OsamaHaikal)
- Gianluca Di Francesco (@gianlucadifrancesco)
- Heb (@Hebilicious)
- Eckhardt (Kaizen) Dreyer (@Eckhardt-D)
- Ismail Sabet (@ismailsabet)
- riskrole (@riskrole)
- Thimo Sietsma (@th1m0)
- felix-dolderer (@felix-dolderer)
- Nicolas Payot (@nicolaspayot)
- Kewin Szlezingier (@kewinzaq1)
- Vasily Kuzin (@ExEr7um)
- Gustav Odinger (@gustavwilliam)
- Martin André (@Martichou)
- Mike Laumann Bellika (@MikeBellika)
- Son Tran (@trandaison)
- rubyisrust (@rubyisrust)
- Riley Ho (@rileychh)
- Potter (@yxw007)
- Martin Masevski (@Archetipo95)
- BoogieBen. (@boogie-ben)
- Tobias Diez (@tobiasdiez)
- Yasser Lahbibi (@yassilah)
- pan93412 (@pan93412)
- AuroraTea (@AuroraTea)
- nuxt-studio[bot] (@nuxt-studio[bot])
- Vaci (@vacijj)
- FELIPE COSTA DE OLIVEIRA (@FelipeO16)
- Aleksei Nagovitsyn (@al3xnag)
- Meo (@miaobuao)
- Mohab Sameh (@mohab-sameh)
- Quentin Macq (@quentinmcq)
- Johan Krijt (@johankrijt)
- arshcodemod (@arshcodemod)
- Santiago A (@santiagoaloi)
- Thomas (@ThomasWT)
- Dominic (@rexhent)
- Florian Metz (@Timeraa)
- Daniel Flanagan (@FlantasticDan)
- 山吹色御守 (@KazariEX)
- izzy goldman (@izzygld)
- Seno (@s-en-o)
- Aviv Keller (@avivkeller)
- Lucie (@lihbr)