What Is New in Nuxt 3
| Category | Highlights |
|---|---|
| New Features |
Nitro server engine with universal deployment; Vue 3 and Composition API as the foundation;
Vite as the default bundler; auto-import system for composables and components;
useAsyncData and useFetch composables; useState for SSR-safe shared state;
file-based server routes under server/; native ESM output; Nuxt Kit for module authoring;
first-class TypeScript support with zero-config type checking
|
| Improvements |
Dramatically smaller production output (single .output directory, no extra Node.js dependencies);
faster HMR via Vite; stable, backward-compatible API with 50+ community modules at launch;
Webpack 5 kept as an alternative bundler; improved runtime config and environment variable handling
|
| Breaking Changes |
asyncData and fetch page hooks removed in favour of composables;
Vuex no longer bundled (Pinia recommended); server middleware replaced by Nitro server routes;
mixin-based patterns replaced by composables; Node.js 12 dropped (14, 16, 18, 19 supported);
evergreen-browsers-only browser target
|
| Deprecations | CommonJS (CJS) module resolution patterns deprecated in favour of native ESM; internal utilities relying on CJS resolve paths removed |
What is the Nitro server engine and why does it matter for deployment?
Nitro is the brand-new server engine at the heart of Nuxt 3, and it fundamentally changes how you ship Vue applications to production.
Instead of producing a Node.js-only server bundle, Nitro compiles your entire application — Vue frontend and server logic together —
into a single, portable .output directory that contains no extra Node.js dependencies beyond necessary polyfills.
In practice, that means the same codebase can be deployed to Node.js servers, serverless functions (AWS Lambda, Vercel, Netlify), edge workers (Cloudflare Workers, Deno Deploy), or even pre-rendered as static files — all by switching a Nitro preset. Most teams will never need to touch infrastructure configuration again for standard deployments.
Watch out for: the server/ directory is now the canonical home for all backend logic. Traditional Nuxt 2 server middleware
goes here as Nitro route handlers. The API is straightforward, but any custom Express middleware you were mounting in
serverMiddleware will need to be rewritten as Nitro event handlers.
// server/api/hello.ts
export default defineEventHandler((event) => {
return { message: 'Hello from Nitro!' }
})
// Accessible at /api/hello automatically - no router config needed
How does data fetching work in Nuxt 3 compared to Nuxt 2?
Nuxt 3 replaces the asyncData and fetch page hooks with two composables: useAsyncData and useFetch.
Both are SSR-aware, meaning they run on the server during the initial render and hydrate seamlessly on the client without a second network round-trip.
useFetch is the ergonomic wrapper for the common case — give it a URL and options, and it handles everything.
useAsyncData is the lower-level primitive you reach for when the data source is not a simple HTTP endpoint
(database query, CMS SDK call, etc.) or when you need fine-grained control over cache keys, deduplication, and refresh strategies.
<script setup lang="ts">
// Simple HTTP fetch - SSR + client hydration handled automatically
const { data: posts, pending, error } = await useFetch('/api/posts')
// Custom async logic with explicit cache key
const { data: user } = await useAsyncData('current-user', () => {
return $fetch('/api/me', { headers: useRequestHeaders(['cookie']) })
})
</script>
This matters if you relied on the Nuxt 2 pattern of returning a plain object from asyncData: the migration is
mostly mechanical, but subtle differences in caching and timing mean you should test every page after conversion.
Pay particular attention to pages that depend on route params — pass the param as the cache key to avoid stale data.
How does Nuxt 3's auto-import system reduce boilerplate?
Nuxt 3 scans your composables/, utils/, and components/ directories and makes every
exported function or component available globally — no import statement required in your .vue files or other composables.
Vue 3 Reactivity APIs like ref, computed, and watch are also auto-imported, as are all Nuxt built-in composables.
In practice, this means a fresh <script setup> block can use useFetch, useState,
useRoute, and your own composable without a single import line at the top. The framework analyses usage at build time
and tree-shakes everything else, so bundle size does not grow just because more utilities are available.
<!-- No imports needed - Nuxt resolves these automatically -->
<script setup lang="ts">
const route = useRoute()
const count = useState('counter', () => 0)
const { data } = await useFetch(`/api/items/${route.params.id}`)
</script>
This matters if you are coming from a large Nuxt 2 codebase: the auto-import system also extends to the server/utils/
directory, keeping server-side helpers DRY. You can also opt third-party packages into the system via the
imports section of nuxt.config.ts.
What does first-class TypeScript support look like in Nuxt 3?
Nuxt 3 was rewritten entirely in TypeScript, and it generates a .nuxt/tsconfig.json and a
.nuxt/nuxt.d.ts global types file automatically, giving you full IDE type coverage with zero manual configuration.
Every built-in composable is typed end-to-end. useFetch infers the response shape from your server route return type
when you co-locate frontend and backend in the same Nuxt project. The CLI exposes a npx nuxi typecheck command
that runs a full type check against your application without starting a dev server, making it straightforward to add to CI pipelines.
// nuxt.config.ts - enable build-time type checking (optional, slower builds)
export default defineNuxtConfig({
typescript: {
typeCheck: true, // runs vue-tsc on every build
strict: true // enables strict mode across the project
}
})
Watch out for: enabling typeCheck: true adds meaningful build time. Most teams leave it off in dev and only
run nuxi typecheck in CI. The strict default in .nuxt/tsconfig.json can also surface latent type
errors in Nuxt 2 code you migrate over — budget time to address them rather than suppressing with any.
What breaking changes should Nuxt 2 teams prepare for when upgrading to Nuxt 3?
Nuxt 3 is not a drop-in upgrade from Nuxt 2 — it is a ground-up rewrite. The most impactful breaking changes for
production teams are the removal of Vuex, the elimination of the asyncData and fetch hooks,
and the shift from options-API mixins to Composition API composables.
The recommended migration path is incremental:
- State management: Replace Vuex stores with Pinia. Pinia integrates natively with Nuxt 3's SSR payload
serialisation, and the mental model maps closely to Vuex 5's original design. The
useStatecomposable covers lighter cases that do not need a full store. - Data fetching: Convert each
asyncDatareturn touseAsyncDataoruseFetch. Keep the cache key unique per page to avoid cross-request data leaking in SSR. - Plugins and modules: The Nuxt Kit API replaces the Nuxt 2 module API entirely. Community modules have been rebuilt; verify compatibility at nuxt.com/modules before migrating any module dependency.
- Server middleware: Move Express or Connect middleware to Nitro event handlers under
server/middleware/orserver/api/. - Mixins: Refactor to composables. There is no mixin support in the Composition API model Nuxt 3 is built on.
Most teams migrate one feature area at a time using Nuxt Bridge on the Nuxt 2 side to progressively adopt Nuxt 3 conventions before making the final jump.
Frequently Asked Questions about Nuxt 3
Is Nuxt 3 production-ready at v3.0.0?
Yes. Nuxt 3.0.0 is the first stable release and ships with a guaranteed backward-compatible API, 50+ supported community modules, and production deployments across Node.js, serverless, and edge platforms.
Do I have to migrate all my components to the Composition API to use Nuxt 3?
No, Vue 3's Options API remains fully supported in Nuxt 3, so existing Options API components will continue to work. However, Nuxt 3 built-in composables like useFetch and useState are designed around the Composition API and script setup, so mixing paradigms in the same component can cause friction. Most teams gradually migrate components to script setup to take full advantage of auto-imports and composable patterns.
What replaces Vuex in Nuxt 3?
Pinia is the officially recommended state management library. It integrates natively with Nuxt 3's SSR serialisation, supports the Composition API, and provides TypeScript inference out of the box. For lighter cases, the built-in useState composable provides SSR-safe reactive state without a full store setup.
How do I run a type check in a Nuxt 3 project?
Run npx nuxi typecheck from the project root. This executes vue-tsc against your application files using the generated .nuxt/tsconfig.json without starting the dev server. You can also set typescript.typeCheck to true in nuxt.config.ts to run type checking automatically on every build, though this adds build time and is typically reserved for CI.
Can I deploy a Nuxt 3 application to Cloudflare Workers or other edge platforms?
Yes. Nitro ships with deployment presets for Cloudflare Workers, Vercel Edge, Deno Deploy, and many other platforms. Switching targets is a one-line change to the nitro.preset option in nuxt.config.ts, and the output is compiled to the appropriate format without any extra tooling.
What Node.js version does Nuxt 3.0 require?
Nuxt 3.0.0 supports Node.js 14, 16, 18, and 19. The team strongly recommends Node.js 18 LTS or later, since Node 14 reached end-of-life shortly after the Nuxt 3 stable release and support for it will be dropped in a future minor version.