Daniel Kelly
Lead Instructor @ Vue School
Full Stack developer (10 years)
Husband and Father
presentation Icons from fontawesome.com
Leveling Up Nuxt
Nuxt 2 → Nuxt 3
Vue
Vue
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
Vue
3
Vue
3
Increased Performance
- ~55% faster overall
- updates up to 33% faster
- memory usage ⬇ 54%
TypeScript Support
- Improved DX
- Zero-config
- Less fragile apps
Composition API
- Better logic reuse
- Flexible code organization
- Better type inference
v3
Universal Rendering
Better Performance
No waiting for browser to
run JS app and render
Improved SEO
Web crawlers directly index
the page's content
Universal Rendering
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
Universal Rendering
Static Site Generation
Cheap, fast, secure hosting
on the Jamstack
New and Improved
💪
Runs Anywhere
Not just Node anymore.
Deno, workers, +
Built for Fast
Cold Starts
Great for serving from
Lambda or Edge Functions
Universal Rendering
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
Tooling
Webpack
Bundling and
development server
with HMR
CLI
Start dev server, build for production, ssg
v2
Tooling
Vite
Lightning fast
development server
with HMR
Nuxi CLI
Everything from Nuxt CLI
plus: file scaffolding, updates,
cleanup, and more!
v3
Tooling
File Structure
File Structure
Conventions
Predictable file structure
that's easy to navigate
Functionality Based
on Directory
Auto imported components,
file-based routing, etc
v2
File Structure
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
/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)
/pages
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
/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
/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
/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
/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
/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"
/components
<LazyMountainsList v-if="show" />
- useful if component is not always needed
- delay loading component until the right moment
- optimize bundle size
combine directory structure to assemble component name
/components
(Duplicate segments are removed)
<BaseFooCustomButton />
extract common UI or code patterns into reusable layouts
/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
/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
/middleware
- anonymous middleware
- named middleware
- global middleware
run code before navigating to a route
/middleware
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
/middleware
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
/middleware
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
/plugins
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
/plugins
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
/plugins
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
/plugins
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
/plugins
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
/plugins
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
File Structure Misc.
v2
Static Assets
v3
Static Assets
Other miscellaneous changes made to the file structure
File Structure Misc.
v2
State Management
Other miscellaneous changes made to the file structure
File Structure Misc.
v2
Server Directory
🤷
v3
Server Directory
REST api routes
runs on every request (including api)
nitro plugins
Currently available resources
Migrate from 2 to 3
Progressively migrate with this compatibility layer for Nuxt 2
Nuxt Bridge
- Nitro
- Vite
- Composition API
- Script Setup
- Auto Imports
Nuxt 3 Fundamentals
Premium Vue Courses
855 lessons • 71 Hours • 45 Courses
51% OFF Black Friday Sale
➕ Plus a FREE workshop!
Thanks!
Leveling Up Nuxt (2->3)
By Daniel Kelly
Leveling Up Nuxt (2->3)
- 1,336