π Highlights
We have a lot of exciting features in v3.8, and can't wait for you to try it out.
π» Nuxi improvements
Just to remind you, we're now using the new Nuxt CLI which is now versioned separately. There are some exciting improvements there to follow, so do check out the latest releases. (For example, we now share the same port with the Vite websocket, meaning better support for docker containers in development.)
π¨ Built-in Nuxt DevTools
Nuxt DevTools v1.0.0 is out and we now think it's ready to be shipped as a direct dependency of Nuxt.
π You can check out the release notes for more information - and stay tuned for an article detailing our roadmap for the future.
πΈ Nuxt Image auto-install
We've now made <NuxtImg>
and <NuxtPicture>
first-class built-in components, documenting them and auto-installing @nuxt/image
the first time that they are used (#23717).
autoinstall2.mp4
We would definitely advise using @nuxt/image
if you're using images in your site; it can apply optimisations to make your site more performant.
π Deeper layout scanning
π¨ This is a behaviour change so do take care with this one: π¨
We now support scanning layouts within subfolders in ~/layouts
in the same way as we do with ~/components
.
File | Layout name |
---|---|
~/layouts/desktop/default.vue | 'desktop-default' |
~/layouts/desktop-base/base.vue | 'desktop-base' |
~/layouts/desktop/index.vue | 'desktop' |
See #20190 for more information
π App Manifest
We now support a built-in app manifest (see #21641), which generates a manifest at /_nuxt/builds/meta/<buildId>.json
.
Initially this enables loading payloads only for prerendered routes, if a site is static (preventing 404s). It also enables client-side route rules. To begin with, only redirect
route rules will have an effect; they will now redirect when performing client-side navigation. (More coming soon...!)
The app manifest also enables future enhancements including detection of outdated deployments by checking /_nuxt/builds/latest.json
.
You can switch off this behaviour if you need to (but do let us know if you have any issues):
export default defineNuxtConfig({
experimental: {
appManifest: false
}
})
π€ Scope and context improvements
We now define a 'scope' for Nuxt composables executed in plugins (#23667), which allows running synchronous cleanup before navigating away from your site, using the Vue onScopeDispose
lifecycle method. This should fix an edge case with cookies (#23697) and also improves memory management, for example in Pinia stores (#23650). You can read more about Vue effect scopes.
We also now support native async context for the Vue composition API (#23526). In case you're unaware, we support native async context on Node and Bun, enabled with experimental.asyncContext
. This can help address issues with missing a Nuxt instance. But it didn't previously affect missing Vue instances.
If you experience issues with 'Nuxt instance unavailable', enabling this option may solve your issues, and once we have cross-runtime support we are likely to enable it by default.
export default defineNuxtConfig({
experimental: {
asyncContext: true
}
})
π NuxtLink defaults
We've supported defining your own NuxtLink
components with the defineNuxtLink
utility. We now support customising the options for the built-in <NuxtLink>
, directly in your nuxt.config
file (#23724). This can enable you to enforce trailing slash behaviour across your entire site, for example.
export default defineNuxtConfig({
experimental: {
defaults: {
nuxtLink: {
activeClass: 'nuxt-link-active',
trailingSlash: 'append'
}
}
}
})
β‘οΈ Data fetching improvements: deep and caching
We have two very significant new features for useAsyncData
and useFetch
:
- You can now set
deep: false
to prevent deep reactivity on thedata
object returned from these composables (#23600). It should be a performance improvement if you are returning large arrays or objects. The object will still update when refetched; it just won't trigger reactive effects if you change a property deep within thedata
. - You can now use the
getCachedData
option to handle custom caching for these composables (#20747)
const nuxtApp = useNuxtApp()
const { data } = await useAsyncData(() => { /* fetcher */ }, {
// this will not refetch if the key exists in the payload
getCachedData: key => nuxtApp.payload.static[key] ?? nuxtApp.payload.data[key]
})
We also support configuring some default values for these composables in an app-wide way (#23725):
export default defineNuxtConfig({
experimental: {
defaults: {
useAsyncData: {
deep: false
},
useFetch: {
retry: false,
retryDelay: 100,
retryStatusCodes: [500],
timeout: 100
}
}
}
})
π’ Layer improvements
We now more carefully load layer plugins (#22889 and #23148) and middleware (#22925 and #23552) in the order of the layers, always loading your own plugins and middleware last. This should mean you can rely on utilities that layers may inject.
We've also added a test suite to cover these layer resolution changes.
And probably one of the most significant changes - if you are using remote layers we now clone these within your node_modules/
folder (#109) so layers can use dependencies with your project. See c12
release notes for full details.
π΄ Nightly release channel
Every commit to the main
branch of Nuxt is automatically deployed to a new release, for easier testing before releases. We've renamed this from the 'edge release channel' to the 'nightly release channel' to avoid confusion with edge deployments. And probably also with Microsoft Edge (though I haven't heard that anyone was confused with that one!)
β‘οΈ nuxt3
is now nuxt-nightly
β‘οΈ nuxi-edge
is now nuxi-nightly
β‘οΈ @βnuxt/kit-edge
is now @βnuxt/kit-nightly
... and so on.
You can read more about how it works.
βοΈ Nitro v2.7
Nitro v2.7 has been released with lots of improvements and bug fixes - do check out the full changelog.
π₯ One of the most significant is that we now save ~40% of bundle size in production by using native fetch
(which is supported in Node 18+) (#1724). So if possible, we'd recommend you update your Node version to at least 18.
πͺ Type import changes
π¨ This is likely to need code changes in your project π¨
Vue requires that type imports be explicit (so that the Vue compiler can correctly optimise and resolve type imports for props and so on). See core Vue tsconfig.json
.
We've therefore taken the decision to turn on verbatimModuleSyntax
by default in Nuxt projects, which will throw a type error if types are imported without an explicit type
import. To resolve it you will need to update your imports:
- import { someFunction, SomeOptions } from 'some-library'
+ import { someFunction } from 'some-library'
+ import type { SomeOptions } from 'some-library'
You may also encounter modules in the Nuxt ecosystem that need to be updated; please open an issue for those modules. I'm also very happy to help if you're encountering any problems with this, if you're a module author. Just tag me and I'll take a look.
If for whatever reason you need to undo this change in your project you can set the following configuration:
export default defineNuxtConfig({
typescript: {
tsConfig: {
compilerOptions: {
verbatimModuleSyntax: false
}
}
}
})
However, we'd recommend only doing that temporarily, as Vue does need this option to be set for best results.
β Upgrading
As usual, our recommendation for upgrading is to run:
nuxi upgrade
π Changelog
π Enhancements
- kit: Add
addServerImports
andaddServerImportsDir
(#23288) - nuxt: Warn when nesting nuxt links when SSR on dev (#23286)
- nuxt: Add
prerenderRoutes
ssr composable (#22863) - nuxt: Enable
appManifest
by default (#23448) - nuxt: Native async-context in vue's
withAsyncContext
(#23526) - nuxt: Auto-install optional features on StackBlitz (#23607)
- kit,nuxt,vite,webpack: Support
-nightly
extension (#23508) - nuxt: Add
@nuxt/devtools
as dependency and enable (#23576) - nuxt: Support
deep: false
for data composables (#23600) - nuxt: Custom cache support for data fetching composables (#20747)
- nuxt: Scan and register layouts in nested folders (#20190)
- nuxt: Prompt to autoinstall
@nuxt/image
when it is used (#23717) - nuxt: Allow configuring default
<NuxtLink>
options (#23724) - nuxt: Allow customising defaults for data composables (#23725)
π₯ Performance
- vite: Don't print server compressed size after vite build (#23359)
- nuxt: Verbatim module syntax + restrict type discovery (#23447)
π©Ή Fixes
- nuxt: Initialise
asyncData
errors withnull
(#23428) - nuxt: Apply scoped styles to islands (#23386)
- nuxt: Rename stub to avoid shadowing
vue-router
(#23440) - nuxt: Stringify cookie values before broadcasting them (#23449)
- kit: Don't force
config.autoImport
inaddServerImports
(#23472) - nuxt: Ignore prefix if
clearNuxtState
called w/o keys (#23483) - nuxt: Decrement hydration count when rendering no route (#23476)
- nuxt: Compute fetch cache key with headers (#23462)
- nuxt: Mock hookable methods on nuxt 2 (#23502)
- kit: Revert accidental change to
addPrerenderRoutes
name (#23509) - nuxt: Use
test
/dev
as manifest buildId when appropriate (#23512) - nuxt: Don't print warnings for unresolved ids (#23604)
- nuxt: Use import alias when checking if plugin is wrapped (#23617)
- nuxt: Tree shake all occurrences of
<DevOnly>
(#23466) - nuxt: Give priority to later middleware when deduping (#23552)
- nuxt: Clear cookie BroadcastChannel when scope is disposed (#23664)
- nuxt: Provide global scope for nuxt plugin context (#23667)
- nuxt: Resolve type error in options of
useFetch
(#23693) - webpack: Remove
lodash-es
+ simplify postcss resolution (#23692) - nuxt: Skip hydration mismatches with client components (#19231)
- nuxt: Write cookie values before navigating away (#23697)
- nuxt: Refetch both undefined/null values in
useAsyncData
(#23351) - nuxt: Don't mark redirected routes as prerendered (#23707)
- nuxt: Respect custom export in component transform (#23715)
- nuxt: Don't use
prerenderedAt
to override app manifest (#23781) - nuxt: Restore
prerenderedAt
behaviour pending next patch (108b1bdf7)
π Documentation
- Mention
listhen
options on nuxi dev page (#23415) - Add examples for index.ts files on server routes (#23390)
- Improve data fetching section (#23420)
- Remove duplicated arrows (#23436)
- Extend description of
handler
foruseAsyncData
(#23389) - Clarify bridge needs
nitro
to useruntimeConfig
(#23454) - Fix typo in README (#23500)
- Clarify that
bridge.typescript
option must be set. (#23503) - Use html instead of xml for highlight (45c1e7f51)
- Fix component library example in docs (#23596)
- Typo in modules (#23602)
- Reword local module info (#23557)
- Add server concept (#23372)
- Improve
nuxt kit
section (#22375) - Update additional mentions to nightly release channel (c63f9a95d)
- Rename
/edge-channel
page to/nightly-release-channel
(#23648) - Add section about computed url for data fetching (#23605)
- Fix typo (#23656)
- Remove extraneous brace (b9cb08cda)
- Fix other issues with
routeRules
example (818dc626c) - Fix typo (#23716)
- Update types for useFetch/useAsyncData (#23730)
- Add info about
<NuxtImg>
and<NuxtPicture>
(#23741) - Update to new website (#23743)
- Remove redundant trailing slashes from links (#23744)
- Fix broken link (#23750)
π‘ Chore
- Fix various typos and update to US English (#23580)
- Add description field for packages (#23734)
- Bump nuxt devtools to 1.0 (#23752)
- Allow markdownlint upgrades (3d779fcf3)
- Remove huntr + encourage GitHub vulnerability reporting (#23754)
- Refresh lockfile (#23755)
- Update to nitropack 2.7.0 (#23780)
- Upgrade to c12 1.5 with configurable layers (#23782)
β Tests
π€ CI
- Retry failing links 6 times (ad2a900fd)
- Only dedupe dependencies if they affect bundle size (#23736)
β€οΈ Contributors
- Daniel Roe (@danielroe)
- Pooya Parsa (@pi0)
- Anthony Fu (@antfu)
- Jianqi Pan (@Jannchie)
- Damian GΕowala (@DamianGlowala)
- SΓ©bastien Chopin (@Atinux)
- Alexander Lichter (@manniL)
- @boc-the-git
- Aleksandar Trpkovski (@Suv4o)
- Dario Ferderber (@darioferderber)
- Warflash (@warflash)
- Julien Huang (@huang-julien)
- Sacha Stafyniak (@stafyniaksacha)
- Alex Liu (@Mini-ghost)
- Orocane (@S1RANN)
- Italo (@DarkGhostHunter)
- @maritaria
- Andrey Yolkin (@Andrey Yolkin)
- Aaron_Zhou (@Clarkkkk)
- EstΓ©ban (@Barbapapazes)
- @sheriffderek
- Eugen Istoc (@genu)
- Mostafa Said (@i-Said-Code)
- Ezra Adeyinka (@adeyinkaezra123)
- Ryota Watanabe (@wattanx)
- Hendrik Heil (@hendrikheil)
- @0xflotus
- Albert Brand (@AlbertBrand)
- Arsen Goian (@arsengoian)
- Maxim (@MaxKostenko)
- Filip Weidemann (@filipweidemann)
- Toni Engelhardt (@toniengelhardt)