Guide

Performance

Optimize your WPNuxt site for speed and Core Web Vitals

This guide covers strategies for building fast WPNuxt sites, from rendering mode selection to query optimization and Core Web Vitals.

SSR vs SSG

SSR (Server-Side Rendering)SSG (Static Site Generation)
Build timeFast (no pre-rendering)Slower (fetches all content at build)
Time to first byte~50-200ms (with caching)~10-50ms (static files)
Content freshnessReal-time (with SWR)Stale until rebuild
Best forFrequently updated sites, many pagesBlogs, documentation, marketing sites
HostingRequires Node.js serverAny static host (CDN)

For most WordPress sites, SSR with caching offers the best balance of freshness and performance. See the SSG guide if your content changes infrequently.

Lazy Loading Composables

Use lazy: true for content that isn't needed for the initial render:

<script setup lang="ts">
// Blocks navigation — use for primary content
const { data: post } = await useNodeByUri({ uri: route.path })

// Doesn't block navigation — use for secondary content
const { data: sidebar, pending } = usePosts(
  { limit: 5 },
  { lazy: true }
)
</script>

This lets the page render immediately with the primary content while secondary content loads in the background.

When to Use Each Mode

ContentOptionEffect
Main page contentawait (default)Blocks navigation, included in SSR HTML
Sidebar, related postslazy: truePage renders immediately, loads in background
Interactive widgetsserver: falseSkips SSR, fetches client-side only
User-triggered contentimmediate: falseNo fetch until execute() is called

See Fetching Data for full options documentation.

Image Optimization

Images are typically the largest assets on a page. Key optimizations:

  1. Set explicit dimensions to prevent Cumulative Layout Shift (CLS):
    <NuxtImg
      :src="imageUrl"
      :width="featuredImage.mediaDetails?.width"
      :height="featuredImage.mediaDetails?.height"
    />
    
  2. Lazy load below-the-fold images:
    <NuxtImg :src="imageUrl" loading="lazy" />
    
  3. Use modern formats with <NuxtPicture> for automatic WebP/AVIF:
    <NuxtPicture :src="imageUrl" format="avif,webp" />
    
  4. Use an image provider (Cloudflare, Vercel, Imgix) for on-the-fly resizing and optimization.

See Images for the full image handling guide.

Route Rules for Per-Route Caching

Configure different caching strategies per route:

nuxt.config.ts
export default defineNuxtConfig({
  routeRules: {
    // Homepage: revalidate frequently
    '/': { swr: 60 },

    // Blog posts: cache longer, SWR for freshness
    '/blog/**': { swr: 3600 },

    // Static pages: cache aggressively
    '/about': { swr: 86400 },

    // API routes: short cache
    '/api/**': { cache: { maxAge: 60 } },
  },
})
Route rules are applied by Nitro at the edge/server level and work independently from WPNuxt's GraphQL caching. Both layers complement each other.

Query Optimization

Use Fragments to Limit Fields

Default fragments include common fields. For listings where you only need titles and URIs, create a lighter fragment:

# extend/queries/fragments/PostListItem.gql
fragment PostListItem on Post {
  id
  title
  uri
  date
  excerpt
  featuredImage {
    node {
      sourceUrl
      altText
    }
  }
}

Set Appropriate Limits

Always set a first value in list queries to avoid fetching more data than needed:

// Fetch only what you need
const { data: posts } = await usePosts({ limit: 10 })

// Don't fetch 100 posts if you show 5
const { data: recent } = await usePosts({ limit: 5 })

Avoid Redundant Fetches

Use clientCache: true (the default) to prevent re-fetching the same data during client-side navigation. See Caching for cache configuration details.

Lighthouse Tips

Largest Contentful Paint (LCP)

  • Use SSR (default) so content is in the initial HTML
  • Avoid lazy: true for above-the-fold content
  • Preload hero images with <NuxtImg preload />
  • Use an image CDN for optimized delivery

Cumulative Layout Shift (CLS)

  • Always provide width and height for images
  • Use placeholder on <NuxtImg> for loading states
  • Avoid content that loads and shifts the layout (use lazy: true only for below-the-fold sections)

Total Blocking Time (TBT)

  • Minimize client-side JavaScript with server: true (default)
  • Use lazy: true to spread hydration work across time
  • Avoid large client-side data transformations — do them server-side in the GraphQL query or in a transform option

Quick Wins Checklist

  • Enable server-side caching (wpNuxt.cache.enabled: true — on by default)
  • Use lazy: true for sidebar and secondary content
  • Set explicit image dimensions to prevent CLS
  • Use loading="lazy" on below-the-fold images
  • Limit query results with first/limit parameters
  • Use an image provider for production (Cloudflare, Vercel, etc.)
  • Configure route rules for per-page caching strategies
Copyright © 2026