Back to Guides

Nuxt.js Performance Optimization

Master Nuxt 3 performance with server-side rendering, Nitro engine, auto-imports, and Vue 3 Composition API best practices.

Why Nuxt Performance Matters

Nuxt 3 is built on Vue 3 and the Nitro engine, offering excellent performance out of the box. However, proper configuration and understanding of Nuxt's features can take your application's speed and Core Web Vitals to the next level.

Nitro Engine

Blazing-fast server engine with universal deployment.

Auto-imports

Automatic tree-shaking with smart auto-imports.

Hybrid Rendering

Mix SSR, SSG, and SPA modes per route.

Vue 3 Optimization

Composition API and script setup for better performance.

1. Leverage Server-Side Rendering

Nuxt 3's SSR capabilities improve initial load time and SEO:

Use Server Routes for Data Fetching

javascript
<script setup>
const { data: posts } = await useFetch('/api/posts');
</script>
<template>
<div v-for="post in posts" :key="post.id">
{{ post.title }}
</div>
</template>

API Routes with Nitro

javascript
// server/api/posts.ts
export default defineEventHandler(async (event) => {
const posts = await getPosts();
return posts;
});

Hybrid Rendering

javascript
// nuxt.config.ts
export default defineNuxtConfig({
routeRules: {
'/': { prerender: true }, // SSG
'/blog/**': { swr: 3600 }, // ISR with 1-hour cache
'/api/**': { cors: true },
'/admin/**': { ssr: false }, // SPA mode
},
});

2. Optimize Auto-Imports and Tree-Shaking

Nuxt 3's auto-imports are optimized by default but can be fine-tuned:

Component Auto-Imports

javascript
// components/TheHeader.vue - automatically imported
<script setup>
// No import needed for composables
const route = useRoute();
const config = useRuntimeConfig();
</script>
<template>
<header>Navigation</header>
</template>

Lazy Load Components

bash
<template>
<div>
<!-- Lazy load with Lazy prefix -->
<LazyHeavyComponent v-if="showHeavy" />
<!-- Or use built-in lazy loading -->
<ClientOnly>
<HeavyChart />
<template #fallback>
<Loading />
</template>
</ClientOnly>
</div>
</template>

Configure Auto-Imports

javascript
// nuxt.config.ts
export default defineNuxtConfig({
imports: {
dirs: [
'composables/**',
'utils/**',
],
},
components: {
dirs: [
{
path: '~/components/global',
global: true,
},
'~/components',
],
},
});

3. Image Optimization with Nuxt Image

Use @nuxt/image for automatic image optimization:

Install and Configure

javascript
# Install
npm install @nuxt/image
# nuxt.config.ts
export default defineNuxtConfig({
modules: ['@nuxt/image'],
image: {
formats: ['webp', 'avif'],
quality: 80,
},
});

Use NuxtImg and NuxtPicture

html
<template>
<!-- Basic usage -->
<NuxtImg src="/hero.jpg" alt="Hero" width="800" height="600" />
<!-- Responsive images -->
<NuxtPicture
src="/hero.jpg"
alt="Hero"
:img-attrs="{ class: 'hero-image' }"
sizes="xs:100vw sm:100vw md:50vw lg:400px"
/>
<!-- Lazy loading -->
<NuxtImg src="/below-fold.jpg" loading="lazy" />
</template>

4. Optimize JavaScript Bundle

Reduce bundle size with code splitting and dynamic imports:

Code Splitting

javascript
// nuxt.config.ts
export default defineNuxtConfig({
build: {
splitChunks: {
layouts: true,
pages: true,
commons: true,
},
},
vite: {
build: {
rollupOptions: {
output: {
manualChunks: {
'chart-library': ['chart.js'],
},
},
},
},
},
});

Analyze Bundle

javascript
# Install analyzer
npm install -D nuxt-build-analyzer
# nuxt.config.ts
export default defineNuxtConfig({
modules: ['nuxt-build-analyzer'],
});
# Run analysis
nuxt build --analyze

5. Caching and State Management

Implement effective caching strategies:

useState for Client-Side State

javascript
<script setup>
// Shared state across components
const counter = useState('counter', () => 0);
// Persist state during SSR hydration
const user = useState('user', () => ({
name: 'Guest',
loggedIn: false,
}));
</script>

useFetch with Caching

javascript
<script setup>
const { data } = await useFetch('/api/posts', {
key: 'posts',
// Cache for 1 hour
getCachedData: (key) => {
const data = nuxtApp.payload.data[key] || nuxtApp.static.data[key];
if (data && Date.now() - data.fetchedAt < 3600000) {
return data;
}
},
});
</script>

Server-Side Caching

javascript
// server/api/posts.ts
import { defineCachedEventHandler } from '#nitro';
export default defineCachedEventHandler(async (event) => {
const posts = await getPosts();
return posts;
}, {
maxAge: 60 * 60, // 1 hour
getKey: () => 'posts',
});

6. Vue 3 Composition API Best Practices

Optimize component performance with modern Vue patterns:

  • Use script setup for better performance and smaller bundles
  • Avoid unnecessary reactive() wrapping for static data
  • Use computed() for derived state instead of watchers
  • Implement v-once for static content that never changes
  • Use shallowRef() and shallowReactive() for large datasets

Optimized Component Example

javascript
<script setup>
import { computed, shallowRef } from 'vue';
// Shallow reactivity for large arrays
const items = shallowRef([]);
// Computed for derived state
const filteredItems = computed(() =>
items.value.filter(item => item.active)
);
</script>
<template>
<div>
<div v-for="item in filteredItems" :key="item.id">
{{ item.title }}
</div>
</div>
</template>

7. Performance Monitoring

Track performance with built-in tools:

  • Use Nuxt DevTools for component performance insights
  • Enable Vue DevTools for reactivity tracking
  • Monitor Core Web Vitals with web-vitals library
  • Use Lighthouse CI in your deployment pipeline

Analyze Your Nuxt App

Get Nuxt-specific optimization recommendations powered by AI.

Test Your Nuxt Site