Performance Optimization
Learn how to optimize your Nuxt Contentstack application for maximum performance. This guide covers caching strategies, request optimization, bundle size reduction, and performance monitoring.
Overview
Performance optimization involves multiple aspects:
- Request Optimization: Reduce API calls and optimize queries
- Caching Strategies: Implement effective caching for static and dynamic content
- Image Optimization: Optimize images for fast loading
- Bundle Size: Reduce JavaScript bundle size
- Code Splitting: Implement proper code splitting strategies
- Monitoring: Track and measure performance metrics
Request Optimization
Reduce API Calls
Minimize the number of API requests by:
1. Batch Related Queries
Instead of multiple separate queries, fetch related content together:
<!-- ❌ Bad - Multiple requests -->
<script setup>
const { data: page } = await useGetEntryByUrl({
contentTypeUid: 'page',
url: '/about'
})
const { data: posts } = await useGetEntries({
contentTypeUid: 'blog_post',
limit: 5
})
</script>
<!-- ✅ Good - Single request with references -->
<script setup>
const { data: page } = await useGetEntryByUrl({
contentTypeUid: 'page',
url: '/about',
referenceFieldPath: ['featured_posts'] // Include related content
})
</script>
2. Use Reference Fields
Include referenced content in a single request:
<script setup>
// ✅ Fetches entry + author + category in one request
const { data: post } = await useGetEntry({
contentTypeUid: 'blog_post',
entryUid: 'blt123',
referenceFieldPath: ['author', 'category', 'related_posts']
})
</script>
3. Limit Fields
Only fetch fields you need (if Contentstack API supports field selection):
<script setup>
// Fetch only necessary fields
const { data: posts } = await useGetEntries({
contentTypeUid: 'blog_post',
limit: 10,
// Use specific field paths if supported
})
</script>
Optimize Query Parameters
Use Appropriate Limits
<script setup>
// ✅ Good - Reasonable limit
const { data: posts } = await useGetEntries({
contentTypeUid: 'blog_post',
limit: 10 // Only fetch what you need
})
// ❌ Bad - Fetching too much
const { data: posts } = await useGetEntries({
contentTypeUid: 'blog_post',
limit: 1000 // Unnecessary data
})
</script>
Implement Pagination
<script setup>
const route = useRoute()
const page = computed(() => parseInt(route.query.page) || 1)
const limit = 10
const skip = computed(() => (page.value - 1) * limit)
const { data: result } = await useGetEntries({
contentTypeUid: 'blog_post',
limit,
skip: skip.value,
includeCount: true
})
</script>
Lazy Loading
Load content only when needed:
<script setup>
// Lazy load content
const { data: posts, pending } = await useGetEntries({
contentTypeUid: 'blog_post',
limit: 10
}, {
lazy: true, // Don't block page load
server: false // Client-side only
})
</script>
Caching Strategies
Static Content Caching
Cache content that rarely changes:
export default defineNuxtConfig({
routeRules: {
'/about': {
swr: 3600, // Cache for 1 hour
headers: {
'Cache-Control': 's-maxage=3600'
}
},
'/blog/**': {
swr: 1800, // Cache for 30 minutes
}
}
})
Dynamic Content Caching
Implement smart caching for frequently updated content:
<script setup>
const { data: posts, refresh } = await useGetEntries({
contentTypeUid: 'blog_post',
limit: 10
})
// Refresh cache periodically
const refreshInterval = setInterval(() => {
refresh()
}, 5 * 60 * 1000) // Every 5 minutes
onUnmounted(() => clearInterval(refreshInterval))
</script>
Cache Invalidation
Invalidate cache when content changes:
export const useContentRefresh = () => {
const refreshAll = async () => {
// Refresh all content composables
await refreshCookie('contentstack')
}
return { refreshAll }
}
Image Optimization
Use @nuxt/image
Leverage Contentstack's image provider for automatic optimization:
<template>
<!-- ✅ Optimized with automatic format conversion -->
<NuxtImg
:src="image.url"
:alt="image.title"
width="800"
height="400"
:modifiers="{ auto: 'webp,compress', quality: 85 }"
provider="contentstack"
loading="lazy"
/>
</template>
Responsive Images
Use responsive images for different screen sizes:
<template>
<NuxtPicture
:src="hero.image.url"
:imgAttrs="{ alt: hero.image.title }"
sizes="100vw sm:90vw md:80vw lg:1200px"
:modifiers="{ quality: 85, auto: 'webp,compress' }"
provider="contentstack"
/>
</template>
Image Preloading
Preload critical images:
<script setup>
const { data: page } = await useGetEntryByUrl({
contentTypeUid: 'page',
url: '/'
})
if (page.value?.hero?.image) {
useHead({
link: [
{
rel: 'preload',
href: page.value.hero.image.url,
as: 'image'
}
]
})
}
</script>
Bundle Size Optimization
Code Splitting
Implement proper code splitting:
<script setup>
// ✅ Lazy load heavy components
const HeavyComponent = defineAsyncComponent(() =>
import('~/components/HeavyComponent.vue')
)
</script>
<template>
<HeavyComponent v-if="showHeavy" />
</template>
Tree Shaking
Import only what you need:
// ✅ Good - Import specific functions
import { useGetEntry } from '#imports'
// ❌ Bad - Import entire module
import * as Contentstack from '#imports'
Reduce Dependencies
Minimize external dependencies:
{
"dependencies": {
"nuxt-contentstack": "^latest",
"@nuxt/image": "^2.0.0"
// Only essential dependencies
}
}
Performance Monitoring
Measure Performance
Use browser DevTools and performance APIs:
export const usePerformance = () => {
const measureContentLoad = (name: string) => {
if (import.meta.client && 'performance' in window) {
const mark = `content-${name}-start`
performance.mark(mark)
return () => {
const endMark = `content-${name}-end`
performance.mark(endMark)
performance.measure(`content-${name}`, mark, endMark)
const measure = performance.getEntriesByName(`content-${name}`)[0]
console.log(`${name} loaded in ${measure.duration}ms`)
}
}
return () => {}
}
return { measureContentLoad }
}
Track API Performance
Monitor API request times:
<script setup>
const startTime = Date.now()
const { data: posts } = await useGetEntries({
contentTypeUid: 'blog_post',
limit: 10
})
const loadTime = Date.now() - startTime
console.log(`Posts loaded in ${loadTime}ms`)
</script>
Best Practices Summary
Do's ✅
- Use reference fields to fetch related content in one request
- Implement proper pagination for large datasets
- Cache static content aggressively
- Optimize images with @nuxt/image
- Use lazy loading for non-critical content
- Monitor performance metrics
- Implement code splitting for large components
Don'ts ❌
- Don't fetch more data than needed
- Don't make unnecessary API calls
- Don't ignore cache invalidation
- Don't load all images immediately
- Don't bundle unnecessary dependencies
- Don't block page load with heavy queries
- Don't ignore performance monitoring
Performance Checklist
Use this checklist to optimize your application:
- Reduced API calls using reference fields
- Implemented pagination for large datasets
- Configured appropriate cache strategies
- Optimized images with @nuxt/image
- Implemented lazy loading for non-critical content
- Reduced bundle size with code splitting
- Set up performance monitoring
- Tested on slow networks
- Verified Core Web Vitals
Next Steps
Personalization
Deliver personalized content experiences with Contentstack Personalize integration, including user attributes, events, and variant-based content delivery.
Live Preview
Enable real-time content editing with Contentstack's Live Preview and Visual Builder integration for seamless content management workflows.