# Nuxt 3 : SSR et génération statique, le guide complet > Maîtrisez le SSR et la génération statique avec Nuxt 3. De useFetch à generateRoutes, découvrez comment optimiser les performances de vos applications Vue. - Published: 2026-02-11 - Updated: 2026-03-31 - Author: SharpSkill - Tags: nuxt 3, vue.js, ssr, génération statique, performance web - Reading time: 12 min --- Nuxt 3 transforme la façon de construire des applications Vue.js en proposant plusieurs modes de rendu adaptés à chaque cas d'usage. Du Server-Side Rendering (SSR) à la génération statique, en passant par le rendu hybride, le framework offre une flexibilité remarquable pour optimiser les performances et le SEO. > **Prérequis** > > Ce tutoriel suppose une connaissance de base de Vue 3 et de la Composition API. Une familiarité avec les concepts de rendu côté serveur est un plus, mais les fondamentaux sont expliqués au fil du guide. ## Comprendre les modes de rendu de Nuxt 3 Avant de plonger dans le code, il est essentiel de comprendre les différences entre les modes de rendu disponibles. Chaque mode répond à des besoins spécifiques en termes de performance, SEO et expérience utilisateur. Le SSR (Server-Side Rendering) génère le HTML sur le serveur à chaque requête. La génération statique (SSG) pré-génère toutes les pages au moment du build. Le mode hybride permet de combiner ces approches page par page. ```typescript // nuxt.config.ts // Configuration des différents modes de rendu export default defineNuxtConfig({ // SSR activé par défaut (recommandé pour le SEO) ssr: true, // Génération statique : pré-rend toutes les pages // Utiliser 'npm run generate' pour builder // target: 'static', // Nuxt 2 syntax // Mode hybride : configurable par route routeRules: { // Page d'accueil : pré-rendue et mise en cache '/': { prerender: true }, // Blog : génération statique '/blog/**': { prerender: true }, // Dashboard : rendu côté client uniquement '/dashboard/**': { ssr: false }, // API : pas de pré-rendu '/api/**': { prerender: false } } }) ``` Cette configuration montre la puissance du mode hybride : chaque section de l'application utilise le mode de rendu le plus adapté à ses besoins. ## Récupération de données avec useFetch et useAsyncData Nuxt 3 propose deux composables principaux pour récupérer des données de manière isomorphique. Ces composables fonctionnent aussi bien côté serveur que côté client, avec une gestion automatique de l'hydratation. `useFetch` est un wrapper autour de `useAsyncData` qui simplifie les appels HTTP. `useAsyncData` offre plus de contrôle pour les cas d'usage avancés. ```vue ``` Pour les cas nécessitant plus de contrôle, `useAsyncData` permet d'exécuter n'importe quelle fonction asynchrone. ```vue ``` Ces composables évitent le double-fetching : les données récupérées sur le serveur sont sérialisées dans le payload HTML et réutilisées lors de l'hydratation côté client. ## Configuration du SSR avec les hooks serveur Le SSR de Nuxt 3 peut être personnalisé grâce aux hooks serveur. Ces hooks permettent d'intervenir à différentes étapes du cycle de rendu pour modifier le comportement par défaut. ```typescript // server/plugins/render-hooks.ts // Plugin serveur pour personnaliser le rendu SSR export default defineNitroPlugin((nitroApp) => { // Hook exécuté avant le rendu de chaque page nitroApp.hooks.hook('render:html', (html, { event }) => { // Injection de scripts ou de métadonnées html.head.push(` `) }) // Hook pour la gestion du cache de rendu nitroApp.hooks.hook('render:response', (response, { event }) => { // Ajout d'en-têtes de cache personnalisés const path = event.path if (path.startsWith('/blog/')) { // Cache long pour les articles de blog response.headers['Cache-Control'] = 'public, max-age=3600, s-maxage=86400' } else if (path.startsWith('/api/')) { // Pas de cache pour les API response.headers['Cache-Control'] = 'no-store' } }) }) ``` > **Performance SSR** > > Le hook `render:response` est idéal pour implémenter des stratégies de cache HTTP. Combiner le SSR avec un CDN qui respecte les headers Cache-Control permet de servir des pages pré-rendues tout en gardant la possibilité de les invalider. ## Génération statique avec nuxt generate La génération statique pré-construit toutes les pages au moment du build. Cette approche est idéale pour les sites à contenu stable comme les blogs, les documentations ou les sites vitrines. Pour les routes dynamiques, Nuxt doit connaître toutes les URLs à générer. Le hook `prerender:routes` permet de définir ces routes programmatiquement. ```typescript // nuxt.config.ts // Configuration complète pour la génération statique export default defineNuxtConfig({ // Activer la génération statique nitro: { prerender: { // Activer le crawling automatique des liens crawlLinks: true, // Routes à toujours inclure routes: ['/', '/about', '/contact'], // Ignorer certaines routes ignore: ['/admin', '/api'] } }, hooks: { // Hook pour générer les routes dynamiques async 'prerender:routes'(ctx) { // Récupération des articles depuis l'API ou la DB const articles = await fetch('https://api.example.com/articles') .then(res => res.json()) // Ajout des routes d'articles for (const article of articles) { ctx.routes.add(`/blog/${article.slug}`) } // Récupération des catégories const categories = await fetch('https://api.example.com/categories') .then(res => res.json()) for (const category of categories) { ctx.routes.add(`/category/${category.slug}`) } } } }) ``` Pour les projets avec un grand nombre de pages, le crawler automatique peut être insuffisant. Voici une approche plus robuste avec un fichier de configuration séparé. ```typescript // server/utils/generate-routes.ts // Utilitaire pour générer la liste des routes dynamiques import { prisma } from './prisma' export async function getAllStaticRoutes(): Promise { const routes: string[] = [] // Articles de blog const articles = await prisma.article.findMany({ where: { published: true }, select: { slug: true, category: { select: { slug: true } } } }) for (const article of articles) { routes.push(`/blog/${article.category.slug}/${article.slug}`) } // Pages produits const products = await prisma.product.findMany({ where: { active: true }, select: { slug: true } }) for (const product of products) { routes.push(`/products/${product.slug}`) } // Pages de tags const tags = await prisma.tag.findMany({ select: { slug: true } }) for (const tag of tags) { routes.push(`/tags/${tag.slug}`) } return routes } ``` ## Rendu hybride avec routeRules Le rendu hybride est la fonctionnalité phare de Nuxt 3. Il permet de définir des règles de rendu différentes selon les routes, combinant le meilleur du SSR et du SSG. ```typescript // nuxt.config.ts // Configuration avancée du rendu hybride export default defineNuxtConfig({ routeRules: { // Pages marketing : pré-rendues et mises en cache longtemps '/': { prerender: true }, '/pricing': { prerender: true }, '/features/**': { prerender: true }, // Blog : ISR (Incremental Static Regeneration) // Revalidation toutes les heures '/blog/**': { isr: 3600, prerender: true }, // Documentation : CDN cache avec revalidation '/docs/**': { swr: 86400, // Stale-while-revalidate prerender: true }, // E-commerce : SSR avec cache court '/products/**': { ssr: true, cache: { maxAge: 60, staleMaxAge: 300 } }, // Panier et checkout : client-side uniquement '/cart': { ssr: false }, '/checkout/**': { ssr: false }, // Dashboard : SPA mode '/dashboard/**': { ssr: false, // Désactiver le prerendering prerender: false }, // API routes : pas de cache par défaut '/api/**': { cors: true, headers: { 'Access-Control-Allow-Methods': 'GET,POST,PUT,DELETE' } } } }) ``` Cette configuration illustre une architecture typique d'application moderne : les pages publiques sont optimisées pour le SEO avec SSG, tandis que les sections interactives utilisent le rendu client. ## Optimisation des performances avec le cache de données Au-delà du cache de pages, Nuxt 3 permet de mettre en cache les données récupérées. Cette stratégie réduit la charge sur les APIs et améliore les temps de réponse. ```typescript // server/api/articles/[slug].get.ts // Endpoint API avec mise en cache des données import { getArticleBySlug } from '~/server/utils/articles' export default defineCachedEventHandler( async (event) => { const slug = getRouterParam(event, 'slug') if (!slug) { throw createError({ statusCode: 400, message: 'Slug manquant' }) } const article = await getArticleBySlug(slug) if (!article) { throw createError({ statusCode: 404, message: 'Article non trouvé' }) } return article }, { // Clé de cache basée sur le slug getKey: (event) => `article-${getRouterParam(event, 'slug')}`, // Durée de vie du cache : 1 heure maxAge: 3600, // Stale-while-revalidate : servir le cache périmé pendant la mise à jour staleMaxAge: 7200, // Invalidation par tags tags: ['articles'] } ) ``` Pour invalider le cache quand le contenu change, Nuxt propose un système de tags. ```typescript // server/api/articles/[slug].put.ts // Mise à jour d'article avec invalidation du cache import { updateArticle } from '~/server/utils/articles' export default defineEventHandler(async (event) => { const slug = getRouterParam(event, 'slug') const body = await readBody(event) // Mise à jour de l'article const article = await updateArticle(slug, body) // Invalidation du cache pour cet article await useStorage('cache').removeItem(`nitro:handlers:article-${slug}`) // Ou invalidation par tag (tous les articles) // await useStorage('cache').clear('articles') return article }) ``` > **Cache distribué** > > En production avec plusieurs instances, le cache en mémoire ne suffit pas. Il est recommandé de configurer un cache Redis ou un autre système distribué via la configuration Nitro pour garantir la cohérence. ## Gestion du SEO et des métadonnées Le SSR permet d'optimiser le SEO en générant les métadonnées côté serveur. Nuxt 3 propose plusieurs approches pour gérer les balises meta de manière dynamique. ```vue ``` Pour les pages statiques, les métadonnées peuvent être définies directement dans le composant. ```vue ``` ## Déploiement et considérations de production Le choix du mode de déploiement dépend du mode de rendu utilisé. Voici les options principales et leurs configurations. ```typescript // nuxt.config.ts // Configuration pour différents environnements de déploiement export default defineNuxtConfig({ nitro: { // Preset selon la plateforme cible // preset: 'vercel', // Vercel // preset: 'netlify', // Netlify // preset: 'cloudflare-pages', // Cloudflare // preset: 'node-server', // Node.js classique // Configuration pour Node.js en production preset: 'node-server', // Compression des réponses compressPublicAssets: true, // Configuration du stockage de cache storage: { cache: { driver: 'redis', url: process.env.REDIS_URL } } }, // Variables d'environnement runtime runtimeConfig: { // Secrets (non exposés au client) apiSecret: process.env.API_SECRET, // Configuration publique public: { apiBase: process.env.NUXT_PUBLIC_API_BASE || '/api' } } }) ``` Pour le déploiement statique, la commande `npm run generate` crée un dossier `.output/public` prêt à être déployé sur n'importe quel hébergeur de fichiers statiques. ```bash # Génération statique npm run generate # Le contenu de .output/public peut être déployé sur : # - Vercel (détection automatique) # - Netlify (configuration automatique) # - GitHub Pages # - S3 + CloudFront # - Tout CDN ou serveur de fichiers statiques ``` ## Conclusion Nuxt 3 offre une flexibilité exceptionnelle pour le rendu des applications Vue.js. Le choix entre SSR, SSG et rendu hybride dépend des besoins spécifiques de chaque projet. **Points clés à retenir :** ✅ **SSR** : idéal pour le contenu dynamique nécessitant un bon SEO (e-commerce, actualités) ✅ **SSG** : parfait pour le contenu stable (blogs, documentation, sites vitrines) ✅ **Hybride** : la meilleure approche pour les applications complexes avec des besoins variés ✅ **useFetch/useAsyncData** : gestion automatique de l'hydratation et du cache ✅ **routeRules** : configuration fine du comportement de chaque route ✅ **Cache** : stratégies multiples pour optimiser les performances en production La combinaison du rendu hybride avec une stratégie de cache bien pensée permet de construire des applications performantes, optimisées pour le SEO, tout en conservant l'interactivité des Single Page Applications. --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/fr/blog/vue-nuxt/nuxt-3-ssr-generation-statique