Let’s balance performance and SEO
In modern web apps, a crucial decision is whether a page should be static or dynamic.
Nuxt 3 offers an elegant answer: Route Rules.
You can set per-route SSR, prerender, cache, or edge behavior. 😌
This post dives into Nuxt 3’s routeRules system—plus cache strategies that optimize both performance and SEO.
What are routeRules?
In nuxt.config.ts, define custom rules per route. These rules decide the rendering mode: SSG, SSR, SPA, or Edge Rendering.// nuxt.config.ts
export default defineNuxtConfig({
routeRules: {
'/': { prerender: true }, // static home
'/blog/**': { swr: 60 }, // 60s cache
'/dashboard/**': { ssr: true, cache: false }, // dynamic area
'/api/**': { cors: true, cache: { maxAge: 300 } } // custom API cache
}
})
Each route behaves on its own—no one-size-fits-all rendering.
TL;DR: routeRules = “Let every route choose its own destiny.”
Key rule meanings
| Rule | Description |
|---|---|
ssr | Should the page render on the server? |
prerender | Generate at build time? |
swr | Stale-While-Revalidate: show cached content while refreshing in the background. |
cache | Fine-tune cache behavior (maxAge, staleMaxAge, etc.). |
cors | Enable CORS for APIs. |
headers | Route-level HTTP headers. |
SSR, SSG, SWR, ISR — what they really mean
SSR (Server-Side Rendering)
Renders on every request.- ✅ Great for dynamic data.
- ❌ More server work per request.
SSG (Static Site Generation)
Built at build time and served from the CDN.- ✅ Fast, cache-friendly.
- ❌ Requires rebuilds for fresh data.
SWR (Stale While Revalidate)
Serve cached content while refreshing periodically.- ✅ Balance of speed + freshness.
- ✅ Users see old content while the new one is prepared in the background.
ISR (Incremental Static Regeneration)
Nuxt’s flavor of SWR—static pages are regenerated incrementally.Example: With /blog/** set to swr: 60, each page is refreshed every 60 seconds.
Example: smart rules for a blog
routeRules: {
'/': { prerender: true }, // static home
'/blog': { prerender: true }, // static list
'/blog/**': { swr: 120 }, // refresh every 2 minutes
'/admin/**': { ssr: true, cache: false } // fully dynamic admin
}
Results:- Home and blog list are prebuilt (fast TTFB).
- Blog detail pages refresh in the background (SWR).
- Admin stays dynamic.
Cache layers
Nuxt 3 manages cache at three levels:- Browser cache: via headers (
Cache-Control). - Server cache: via Nitro (
cache: { maxAge }). - CDN cache: Cloudflare, Netlify Edge, Vercel, etc.
Example
'/api/posts': {
cache: {
maxAge: 300, // 5 minutes
staleMaxAge: 60 // show stale cache during this window
}
}
This avoids re-running the API for every request.💡 Tip: Nitro’s cache works both on server and edge.
Dynamic vs static — decision matrix
| Scenario | Strategy |
|---|---|
| Blog pages | SWR / ISR |
| Dashboard / Admin | SSR |
| Home page | SSG / Prerender |
| API endpoint | Cache + SSR |
| Real-time (e.g., chat) | SSR (or server streaming) |
Gotchas
- With
swr, your data should be idempotent (same request → same response). - For cached APIs that vary by user (JWT, cookies), beware of cache sharing and leakage.
- Caching SSR routes can show the wrong data to the wrong user—be careful.
Advanced: routeRules + Nitro
Nuxt’s Nitro engine pushesrouteRules down to edge environments (Cloudflare, Netlify, Vercel Edge Functions). Static and dynamic can happily coexist in one codebase.routeRules: {
'/api/**': { cache: { maxAge: 60 }, headers: { 'x-powered-by': 'Nuxt Nitro' } }
}
Now even your API responses are cached at the edge.Conclusion
Route Rules are one of Nuxt 3’s strongest—yet least known—features. Define per-page and per-API rendering and caching to optimize your app.In short:
prerender→ Static pagesswr→ Fast pages that stay freshssr→ Dynamic areascache→ Smart API performance