Nuxt 3 architecture rework — performance & SSR

We’re currently restructuring our Nuxt 3 app due to performance issues. Our pages are rendered via a two-step waterfall: First API call: get route metadata (e.g. pageType, id) Second API call: fetch actual content based on the above 🛠️ What we're proposing: We plan to refactor to SSR fully-rendered pages, and cache them globally via Fastly at the edge. Key improvements: Eliminate the waterfall with server-side unified data fetching Use middleware to attach Cache-Control dynamically per page type Add a webhook to purge/update articles on demand Maybe Cache articles "forever" unless edited; use stale-while-revalidate for home/category pages Live examples of our current Nuxt setup: https://illvid.dk https://historienet.dk https://bilmagasinet.dk https://woman.dk ❓What we’re wondering: Are we approaching SSR + edge caching in a Nuxt-idiomatic way? Would you structure content fetching differently? (Currently planning to centralize route/content resolution into a single server API and preload in serverPrefetch or top-level asyncData) Any tips for performance wins in similar Nuxt 3 apps? side note: we have seen that our search crawlers often see empty <main><!-- --></main> pages during hydration, hurting our SEO, however we can not seem to reproduce this is in any living way, and even our crawls not always see this problem on the same url.
Illustreret Videnskab - gå på opdagelse i videnskabens verden
Illustreret Videnskab er et internationalt populærvidenskabeligt magasin, som giver læseren indsigt i verdens førende forskning i alle grene af videnskaben.
Gå på opdagelse i verdenshistoriens største dramaer
Magasinet HISTORIE tager dig med på en hæsblæsende rejse til fortiden, hvor du kan nyde historiens største dramaer fra forreste række.
Nyheder, guides og test af nye og brugte biler
"Find de nyeste biltests, anmeldelser og guides til biler fra Bilmagasinet. Hold dig opdateret på alt om biler, nyheder, elbiler, SUV'er og meget mere."
Woman | Danmarks bedste kvindeunivers
Her får du inspiration indenfor livsstil og underholdning samt indsigt i aktuelle emner, der optager os alle lige nu.
2 Replies
kapa.ai
kapa.ai3mo ago
Hi @Nicklas Degnebolig. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- Your proposed SSR + edge caching approach is very much in line with Nuxt 3’s idiomatic best practices for high-performance, content-heavy sites. Here’s a breakdown based on the official documentation and best practices: --- 1. SSR with Unified Data Fetching Centralizing data fetching on the server (eliminating the two-step waterfall) is recommended. Nuxt’s SSR mode is designed to fetch all required data server-side, render the HTML, and send it to the client for hydration. This ensures crawlers and users always receive fully populated HTML, which is critical for SEO and perceived performance. - Use useFetch or useAsyncData in your top-level page components to fetch all necessary data in a single request. These composables ensure that data fetched on the server is serialized and reused on the client during hydration, preventing double-fetching and hydration mismatches. Avoid using $fetch directly in the setup function for SSR-critical data, as it can cause double-fetching and hydration issues Data Fetching. - Centralizing route/content resolution into a single server API is a good pattern, especially for complex content models. --- 2. Edge Caching with Fastly Nuxt 3 (via Nitro) is designed for universal deployment, including edge networks. You can use route rules to control caching and rendering per route, which is ideal for your use case: - Use routeRules in nuxt.config.ts to define cache strategies, SSR toggling, and more per route. For example, you can set prerender, swr, or isr for different page types, and disable SSR for admin routes Hybrid Rendering. - For edge caching, ensure your server sets appropriate Cache-Control headers. You can use server middleware to dynamically attach these headers based on page type Server. - Your plan to cache articles "forever" unless edited, and use stale-while-revalidate for home/category pages, matches the recommended use of swr and isr route rules. --- 3. Webhook-based Purge/Update This is a common and effective pattern. When content is updated, trigger a webhook to purge the relevant cache at the edge (Fastly). This ensures users and crawlers always see fresh content when needed. --- 4. Performance Tips - Avoid redundant data fetching: Use useFetch/useAsyncData to prevent double-fetching and ensure SSR data is reused on the client Performance Best Practices. - Lazy load components and use lazy hydration for non-critical UI parts. - Profile your app with Nuxt DevTools, Chrome DevTools, and PageSpeed Insights to identify bottlenecks. - Optimize images and fonts with Nuxt Image and Nuxt Fonts modules. - Minimize plugins and global middleware to reduce JS bundle size and execution time. --- 5. SEO & Hydration Issues The issue with crawlers sometimes seeing empty <main><!-- --></main> is often due to hydration mismatches or data not being available at SSR time. To avoid this: - Always use SSR-friendly data fetching (useFetch/useAsyncData) for content that must be present in the initial HTML. - Ensure that all data required for rendering is available before the server sends the HTML. Avoid client-only fetching for SEO-critical content. - If you have conditional logic or browser-only code, wrap it with import.meta.client to prevent it from running during SSR Nuxt Lifecycle. - Use Nuxt DevTools to inspect the payload and SSR output for problematic routes. --- 6. Example: routeRules for Hybrid Rendering
export default defineNuxtConfig({
routeRules: {
'/': { swr: true }, // Home: stale-while-revalidate
'/category/**': { swr: true }, // Categories: SWR
'/article/**': { isr: true }, // Articles: cache until next deploy or purge
'/admin/**': { ssr: false }, // Admin: client-only
}
})
export default defineNuxtConfig({
routeRules: {
'/': { swr: true }, // Home: stale-while-revalidate
'/category/**': { swr: true }, // Categories: SWR
'/article/**': { isr: true }, // Articles: cache until next deploy or purge
'/admin/**': { ssr: false }, // Admin: client-only
}
})
Hybrid Rendering --- Summary:
Your approach is Nuxt-idiomatic and leverages the framework’s strengths. Focus on SSR-friendly data fetching, use route rules for caching and rendering, and ensure all SEO-critical content is rendered server-side. Use DevTools to debug hydration and SSR output. Your plan should resolve both performance and SEO issues if implemented as described. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3mo ago
<@141551222757916673> Kapa.ai is still learning and improving, please let me know how I did by reacting below.

Did you find this page helpful?