Cours Vue.js · Module 15: TypeScript et Nuxt
Concepts SSR : SPA vs SSR vs SSG vs ISR
Dans cette leçon6
Le Centre de Commandement NOVA LAB doit transmettre les informations le plus rapidement possible. Les différentes stratégies de rendu sont comme les différents systèmes de communication de la station - chacune a ses avantages selon la situation.
SPA - Single Page Application
Une application Vue classique est une SPA (Single Page Application) :
- Le navigateur télécharge un fichier HTML vide
- Il charge le JavaScript (le bundle Vue)
- Le JavaScript rend toute la page dans le navigateur
- La navigation se fait sans rechargement de page
1Serveur → [HTML vide + bundle JS] → Navigateur → [rendu]Avantages de la SPA :
- Navigation fluide sans rechargements
- Interactivité riche
- Hébergement simple (fichiers statiques)
Inconvénients de la SPA :
- Chargement initial lent (bundle JS volumineux)
- Page vide jusqu'au chargement du JS
- Mauvais référencement (SEO) - les robots voient un HTML vide
SSR - Server-Side Rendering
Le SSR rend la page sur le serveur et envoie du HTML prêt à l'emploi :
- Le serveur reçoit une requête
- Vue rend le composant en HTML sur le serveur
- Il envoie le HTML prêt au navigateur
- Le navigateur affiche la page immédiatement
- Le JavaScript est chargé et « hydrate » la page (ajoute l'interactivité)
1Requête → Serveur [rend le HTML] → Navigateur [affichage + hydratation]Avantages du SSR :
- First Contentful Paint (FCP) plus rapide
- Excellent référencement (SEO) - les robots voient le HTML complet
- Meilleures performances sur les appareils lents
Inconvénients du SSR :
- Charge serveur plus élevée
- Time to Interactive (TTI) plus long
- Infrastructure plus complexe
SSG - Static Site Generation
Le SSG génère le HTML au moment du build :
- Pendant
npm run build- chaque page est prérendue en HTML - Les fichiers HTML sont prêts à être servis
- Aucun serveur nécessaire - simple hébergement statique
- Le JavaScript hydrate la page côté client
1Build time → [génère le HTML] → Déploiement → CDN → NavigateurAvantages du SSG :
- Réponse la plus rapide possible (fichiers depuis un CDN)
- Aucun serveur - l'option la moins chère
- Excellent référencement (SEO)
Inconvénients du SSG :
- Le contenu ne change pas entre deux builds
- Chaque modification nécessite un rebuild
- Inadapté aux données dynamiques
ISR - Incremental Static Regeneration
L'ISR combine SSG et SSR - les pages sont générées statiquement mais peuvent se rafraîchir :
- Première visite - la page est servie depuis le cache statique
- Après un délai défini - la page est régénérée en arrière-plan
- La visite suivante reçoit la version mise à jour
1Requête → [cache/CDN] → si périmé → régénération en arrière-plan → nouvelle versionAvantages de l'ISR :
- Vitesse du SSG + fraîcheur du SSR
- Rafraîchissement automatique
Inconvénients de l'ISR :
- Configuration plus complexe
- Les données peuvent être momentanément périmées (stale-while-revalidate)
L'hydratation - la clé de l'interactivité
L'hydratation est le processus par lequel Vue « reprend le contrôle » du HTML statique généré par le serveur et y ajoute l'interactivité :
1Serveur : <button>Click</button> ← HTML statique
2 ↓ hydratation
3Client : <button @click="handler">Click</button> ← interactifVue compare le DOM virtuel au HTML existant et attache les gestionnaires d'événements, les refs et la réactivité - sans refaire le rendu de tout le DOM.
Quand utiliser quelle stratégie ?
| Stratégie | À utiliser quand... |
|---|---|
| SPA | L'app demande une interactivité riche (dashboard, éditeur) |
| SSR | Le SEO compte + données dynamiques (boutique, blog avec commentaires) |
| SSG | Le contenu change rarement (documentation, landing page) |
| ISR | Le contenu change, mais pas en temps réel (blog, catalogue) |
Code de cette leçon : App.vue
1<script setup lang="ts">
2import { ref } from 'vue'
3
4type RenderStrategy = 'SPA' | 'SSR' | 'SSG' | 'ISR'
5
6interface StrategyInfo {
7 name: RenderStrategy
8 fullName: string
9 description: string
10 pros: string[]
11 cons: string[]
12 useCase: string
13 color: string
14}
15
16const strategies = ref<StrategyInfo[]>([
17 {
18 name: 'SPA',
19 fullName: 'Single Page Application',
20 description: 'Rendering in the browser after JS loads',
21 pros: ['Navigation fluide', 'Interactivité riche', 'Hébergement simple'],
22 cons: ['Slow loading', 'Weak SEO', 'Empty HTML'],
23 useCase: 'Dashboard, éditeur, application interne',
24 color: '#00b4d8'
25 },
26 {
27 name: 'SSR',
28 fullName: 'Server-Side Rendering',
29 description: 'Le serveur rend le HTML et envoie une page prête',
30 pros: ['FCP rapide', 'Excellent SEO', 'Meilleures performances'],
31 cons: ['Charge serveur', 'TTI plus long', 'Infrastructure complexe'],
32 useCase: 'Boutique, blog, réseaux sociaux',
33 color: '#00ff88'
34 },
35 {
36 name: 'SSG',
37 fullName: 'Static Site Generation',
38 description: 'HTML généré au moment du build',
39 pros: ['Fastest response', 'No server', 'Excellent SEO'],
40 cons: ['Static content', 'Rebuild on change', 'Not for dynamic data'],
41 useCase: 'Documentation, landing page, portfolio',
42 color: '#9b59b6'
43 },
44 {
45 name: 'ISR',
46 fullName: 'Incremental Static Regeneration',
47 description: 'Pages statiques rafraîchies en arrière-plan',
48 pros: ['Vitesse du SSG + fraîcheur du SSR', 'Rafraîchissement automatique'],
49 cons: ['Complex configuration', 'Temporarily stale data'],
50 useCase: 'Blog, catalogue, site vitrine',
51 color: '#f39c12'
52 }
53])
54
55const selected = ref<RenderStrategy>('SPA')
56
57const current = ref<StrategyInfo>(strategies.value[0])
58
59function selectStrategy(name: RenderStrategy) {
60 selected.value = name
61 current.value = strategies.value.find(s => s.name === name)!
62}
63</script>
64
65<template>
66 <div class="nova-lab">
67 <h1>Stratégies de rendu</h1>
68
69 <div class="tabs">
70 <button
71 v-for="s in strategies"
72 :key="s.name"
73 @click="selectStrategy(s.name)"
74 :class="{ active: selected === s.name }"
75 :style="{ borderColor: s.color }"
76 >
77 {{ s.name }}
78 </button>
79 </div>
80
81 <div class="detail" :style="{ borderColor: current.color }">
82 <h2 :style="{ color: current.color }">{{ current.name }}</h2>
83 <p class="fullname">{{ current.fullName }}</p>
84 <p class="desc">{{ current.description }}</p>
85
86 <div class="lists">
87 <div>
88 <h4 style="color: #00ff88">Avantages</h4>
89 <ul>
90 <li v-for="pro in current.pros" :key="pro">{{ pro }}</li>
91 </ul>
92 </div>
93 <div>
94 <h4 style="color: #e74c3c">Inconvénients</h4>
95 <ul>
96 <li v-for="con in current.cons" :key="con">{{ con }}</li>
97 </ul>
98 </div>
99 </div>
100
101 <div class="use-case">
102 <strong>Utilisation :</strong> {{ current.useCase }}
103 </div>
104 </div>
105 </div>
106</template>
107
108<style scoped>
109.nova-lab {
110 background: #0a0e27;
111 color: #00ff88;
112 min-height: 100vh;
113 padding: 20px;
114 font-family: monospace;
115}
116h1 { color: #00ff88; margin-bottom: 15px; }
117h2 { margin-bottom: 4px; }
118.tabs { display: flex; gap: 8px; margin-bottom: 15px; }
119.tabs button {
120 background: rgba(0,180,216,0.1);
121 color: #ccc;
122 border: 2px solid #333;
123 padding: 10px 20px;
124 border-radius: 8px;
125 cursor: pointer;
126 font-family: monospace;
127 font-weight: bold;
128}
129.tabs button.active {
130 background: rgba(0,180,216,0.25);
131 color: white;
132}
133.detail {
134 background: rgba(0,180,216,0.06);
135 border: 2px solid #00b4d8;
136 padding: 20px;
137 border-radius: 12px;
138}
139.fullname { color: #888; font-size: 13px; margin-bottom: 8px; }
140.desc { color: #ccc; margin-bottom: 12px; }
141.lists { display: flex; gap: 20px; margin-bottom: 12px; }
142.lists ul { list-style: none; padding: 0; }
143.lists li { padding: 3px 0; font-size: 13px; color: #ccc; }
144.lists li::before { content: '> '; color: #00b4d8; }
145h4 { margin-bottom: 6px; }
146.use-case {
147 background: rgba(0,255,136,0.08);
148 padding: 10px 14px;
149 border-radius: 8px;
150 font-size: 13px;
151 color: #00b4d8;
152}
153</style>Tu as repéré une erreur dans cette leçon ?
Teste tes connaissances
Réponds aux questions de cette leçon. Choisis une réponse pour voir tout de suite si elle est correcte.
1. Que signifie le SSR (Server-Side Rendering) ?
2. Qu'est-ce que l'hydratation dans le contexte du SSR ?
Voici 2 des 3 questions de cette leçon. Réponds aux autres dans le jeu.
Tâches pratiques dans le jeu
- Éditeur de code
Définis un type union RenderStrategy et une interface StrategyInfo.
- Tri vertical
Ordonne les étapes du processus de Server-Side Rendering :
- Éditeur de code
Définis une interface CrewMember et type les états data, pending, error.
- Tri vertical
Ordonne l'ordre de chargement d'une SPA (Single Page Application) :
- Clique dans l'ordre
Ordonne les stratégies de rendu du First Contentful Paint le plus rapide au plus lent :
- Éditeur de code
Définis un type union Page et type la navigation entre les pages.