Lead Instructor @ Vue School
Full Stack developer (10 years)
Husband and Father
presentation Icons from fontawesome.com
Nuxt 2 → Nuxt 3
Dynamic/Reactive Frontends
<template>
<div>
<h1>Nuxt is Awesome!</h1>
<ul v-auto-animate>
<li
v-for="reason in soManyReasons"
:key="reason">
{{ reason }}
</li>
</ul>
</div>
</template>
Templating
v2
Increased Performance
TypeScript Support
Composition API
v3
Better Performance
No waiting for browser to
run JS app and render
Improved SEO
Web crawlers directly index
the page's content
Static Site Generation
Cheap, fast, secure hosting
on the Jamstack
v2
Better Performance
No waiting for browser to
run JS app and render
Improved SEO
Web crawlers directly index
the page's content
Static Site Generation
Cheap, fast, secure hosting
on the Jamstack
Runs Anywhere
Not just Node anymore.
Deno, workers, +
Built for Fast
Cold Starts
Great for serving from
Lambda or Edge Functions
Hybrid Rendering
Support multiple
rendering modes on a
single app
v3
Hybrid Rendering
export default defineNuxtConfig({
routeRules: {
// Static page generated on-demand, revalidates in background
'/blog/**': { swr: true },
// Static page generated on-demand once
'/articles/**': { static: true },
// Set custom headers matching paths
'/_nuxt/**': { headers: { 'cache-control': 's-maxage=0' } },
// Render these routes with SPA
'/admin/**': { ssr: false },
// Add cors headers
'/api/v1/**': { cors: true },
// Add redirect headers
'/old-page': { redirect: '/new-page' },
'/old-page2': { redirect: { to: '/new-page', statusCode: 302 } }
}
})
v3
Hybrid Rendering
v3
Zero-Config Deploys
Or minimal config deploys
v3
Webpack
Bundling and
development server
with HMR
CLI
Start dev server, build for production, ssg
v2
Vite
Lightning fast
development server
with HMR
Nuxi CLI
Everything from Nuxt CLI
plus: file scaffolding, updates,
cleanup, and more!
v3
Conventions
Predictable file structure
that's easy to navigate
Functionality Based
on Directory
Auto imported components,
file-based routing, etc
v2
Conventions
Predictable file structure
that's easy to navigate
Functionality Based
on Directory
Auto imported components,
file-based routing, etc
V3 Enhancments
Nuxt 3 adds conventions
and added functionality
v3
routes created based on structure (including dynamic routes)
/pages/edit-[id].vue
v2
/pages/_id.vue
Dynamic Params
/pages/[id].vue
v3
Dynamic Params
/pages/_.vue
Catch All
/pages/[...slug].vue
Catch All
<NuxtLink to="/123">Post 123</NuxtLink>
routes created based on structure (including dynamic routes)
v3
Page Meta
// MyPage.vue
definePageMeta({
middleware: ["auth"],
pageTransition: 'fade',
layout: 'blog',
})
useHead({
title: "Hello World"
})
v2
Page Meta
// MyPage.vue
export default {
middleware: 'auth',
transition: 'fade',
layout: 'blog',
head() {
return {
title: 'Hello World',
}
}
}
predictable location to store Vue Single File components
v3
Auto Imports
// it's automatic!
v2
Auto Imports
// nuxt.config.js
export default {
components: true
}
🔥 so are composables!
/composables
predictable location to store Vue Single File components
v3
Client Only
// MyPage.vue
<template>
<ClientOnly>
<MyComponent/>
</ClientOnly>
</template>
v2
Client Only
// MyPage.vue
<template>
<ClientOnly>
<MyComponent/>
</ClientOnly>
</template>
predictable location to store Vue Single File components
v2
Client Only
// MyPage.vue
<template>
<ClientOnly>
<MyComponent/>
</ClientOnly>
</template>
v3
Client Only
// MyPage.vue
<template>
<MyComponent/>
</template>
MyComponent.client.vue
MyComponent.server.vue
predictable location to store Vue Single File components
MyComponent.client.vue
v2
Client Only
// MyPage.vue
<template>
<ClientOnly>
<MyComponent/>
</ClientOnly>
</template>
v3
Client Only
// MyPage.vue
<template>
<MyComponent/>
</template>
// MyComponent.server.vue
<template>
Loading...
</template>
MyComponent.server.vue
MyComponent.client.vue
predictable location to store Vue Single File components
MyComponent.client.vue
v2
Client Only
// MyPage.vue
<template>
<ClientOnly>
<MyComponent/>
</ClientOnly>
</template>
v3
Client Only
// MyPage.vue
<template>
<MyComponent/>
</template>
// MyComponent.client.vue
<script setup>
$fetch("http://myapi.com")
</script>
MyComponent.client.vue
lazy load components by prefixing with "lazy"
<LazyMountainsList v-if="show" />
combine directory structure to assemble component name
(Duplicate segments are removed)
<BaseFooCustomButton />
extract common UI or code patterns into reusable layouts
v3
Render Page
// layouts/default.vue
<template>
<div>
<slot />
</div>
</template>
v2
Render Page
// layouts/default.vue
<template>
<Nuxt />
</template>
⚠️ must provide wrapper!
extract common UI or code patterns into reusable layouts
v3
Render Page
// ~/error.vue
<template>
<pre> {{error}} </pre>
</template>
<script setup>
defineProps({
error: Object
})
</script>
v2
Error Page
// layouts/error.vue
<template>
<pre> {{error}} </pre>
</template>
<script>
export default {
props: ['error'],
}
</script>
run code before navigating to a route
run code before navigating to a route
v2
Global Middleware
// nuxt.config.js
export default{
router: {
middleware: 'log',
},
}
~/middleware/log.js
v3
Global Middleware
~/middleware/log.global.js
run code before navigating to a route
v2
Middleware Definition
// middleware/log.js
export default function (context) {
console.log("hello")
}
v3
Middleware Definition
// middleware/log.js
export default defineNuxtRouteMiddleware((to, from) => {
console.log("hello")
})
run code before navigating to a route
v2
Middleware Definition
// middleware/log.js
export default function ({redirect}) {
return redirect("/login")
}
v3
Middleware Definition
// middleware/log.js
export default defineNuxtRouteMiddleware((to, from) => {
return navigateTo('/login')
})
provide global helpers, register Vue plugins and directives
v2
Register Plugins
// nuxt.config.js
export default {
plugins: ['~/plugins/tooltip.js']
}
v3
Register Plugins
🔥 auto registered!
provide global helpers, register Vue plugins and directives
v2
Register Vue Plugin
// ~/plugins/tooltip.js
import Vue from 'vue'
import VTooltip from 'v-tooltip'
Vue.use(VTooltip)
v3
Register Vue Plugin
// ~/plugins/tooltip.js
import VTooltip from 'v-tooltip'
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.use(VTooltip)
})
provide global helpers, register Vue plugins and directives
v2
Register Vue Plugin
// ~/plugins/tooltip.client.js
import Vue from 'vue'
import VTooltip from 'v-tooltip'
Vue.use(VTooltip)
v3
Register Vue Plugin
// ~/plugins/tooltip.client.js
import VTooltip from 'v-tooltip'
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.use(VTooltip)
})
provide global helpers, register Vue plugins and directives
v2
Global Helpers
// ~/plugins/tooltip.js
export default ({ app }, inject) => {
inject(
'hello',
msg => console.log(`Hello ${msg}!`)
)
}
v3
Global Helpers
// ~/plugins/tooltip.js
export default defineNuxtPlugin(() => {
return {
provide: {
hello: (msg: string) => `Hello ${msg}!`
}
}
})
provide global helpers, register Vue plugins and directives
v2
Global Helpers
// MyComponent.vue
<template>
<div>{{ $hello('world') }}</div>
</template>
v3
Global Helpers
// MyComponent.vue
<template>
<div>{{ $hello('world') }}</div>
</template>
provide global helpers, register Vue plugins and directives
v2
Global Helpers
// MyComponent.vue
<script>
export default {
created() {
this.$hello('mounted')
}
}
</script>
v3
Global Helpers
// MyComponent.vue
<script setup lang="ts">
const { $hello } = useNuxtApp()
</script>
Just use a composable 🤔
Other miscellaneous changes made to the file structure
v2
Static Assets
v3
Static Assets
Other miscellaneous changes made to the file structure
v2
State Management
Other miscellaneous changes made to the file structure
v2
Server Directory
🤷
v3
Server Directory
REST api routes
runs on every request (including api)
nitro plugins
Currently available resources
Progressively migrate with this compatibility layer for Nuxt 2
855 lessons • 71 Hours • 45 Courses
➕ Plus a FREE workshop!