Vue.js course Β· Module 15: TypeScript & Nuxt
SSR Concepts: SPA vs SSR vs SSG vs ISR
In this lesson6
The NOVA LAB Command Center must deliver information as quickly as possible. Different rendering strategies are like different communication systems on the station - each has its advantages depending on the situation.
SPA - Single Page Application
A traditional Vue application is an SPA (Single Page Application):
- The browser downloads an empty HTML file
- It loads the JavaScript (Vue bundle)
- JavaScript renders the entire page in the browser
- Navigation happens without page reloads
1Server β [empty HTML + JS bundle] β Browser β [rendering]SPA Advantages:
- Smooth navigation without reloads
- Rich interactivity
- Simple hosting (static files)
SPA Disadvantages:
- Slow initial load (large JS bundle)
- Empty page until JS loads
- Poor SEO - bots see empty HTML
SSR - Server-Side Rendering
SSR renders the page on the server and sends ready HTML:
- The server receives a request
- Vue renders the component on the server to HTML
- It sends the ready HTML to the browser
- The browser displays the page immediately
- JavaScript is loaded and "hydrates" the page (adds interactivity)
1Request β Server [renders HTML] β Browser [displays + hydration]SSR Advantages:
- Faster First Contentful Paint (FCP)
- Excellent SEO - bots see full HTML
- Better performance on slow devices
SSR Disadvantages:
- Higher server load
- Longer Time to Interactive (TTI)
- More complex infrastructure
SSG - Static Site Generation
SSG generates HTML at build time:
- During
npm run build- each page is prerendered to HTML - HTML files are ready to be served
- No server needed - plain static hosting
- JavaScript hydrates the page on the client
1Build time β [generates HTML] β Deploy β CDN β BrowserSSG Advantages:
- Fastest possible response (files from CDN)
- No server - cheapest option
- Excellent SEO
SSG Disadvantages:
- Content doesn't change between builds
- Every change requires a rebuild
- Not suitable for dynamic data
ISR - Incremental Static Regeneration
ISR combines SSG and SSR - pages are generated statically but can refresh:
- First visit - page served from static cache
- After a set time - the page is regenerated in the background
- Next visit gets the updated version
1Request β [cache/CDN] β if stale β regenerate in background β new versionISR Advantages:
- SSG speed + SSR freshness
- Automatic refreshing
ISR Disadvantages:
- More complex configuration
- Data may be momentarily outdated (stale-while-revalidate)
Hydration - the Key to Interactivity
Hydration is the process where Vue "takes over" the static HTML generated by the server and adds interactivity to it:
1Server: <button>Click</button> β static HTML
2 β hydration
3Client: <button @click="handler">Click</button> β interactiveVue compares the virtual DOM with the existing HTML and attaches event handlers, refs, and reactivity - without re-rendering the entire DOM.
When to Use Which Strategy?
| Strategy | Use when... |
|---|---|
| SPA | The app requires rich interactivity (dashboard, editor) |
| SSR | SEO matters + dynamic data (store, blog with comments) |
| SSG | Content changes rarely (documentation, landing page) |
| ISR | Content changes, but not in real time (blog, catalog) |
Code for this lesson: 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: ['Smooth navigation', 'Rich interactivity', 'Simple hosting'],
22 cons: ['Slow loading', 'Weak SEO', 'Empty HTML'],
23 useCase: 'Dashboard, editor, internal application',
24 color: '#00b4d8'
25 },
26 {
27 name: 'SSR',
28 fullName: 'Server-Side Rendering',
29 description: 'The server renders HTML and sends a ready page',
30 pros: ['Fast FCP', 'Excellent SEO', 'Better performance'],
31 cons: ['Server load', 'Longer TTI', 'Complex infrastructure'],
32 useCase: 'Store, blog, social media',
33 color: '#00ff88'
34 },
35 {
36 name: 'SSG',
37 fullName: 'Static Site Generation',
38 description: 'HTML generated at build time (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: 'Static pages refreshed in the background',
48 pros: ['SSG speed + SSR freshness', 'Automatic refresh'],
49 cons: ['Complex configuration', 'Temporarily stale data'],
50 useCase: 'Blog, catalog, company website',
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>Rendering Strategies</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">Pros</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">Cons</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>Use case:</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>Spotted a mistake in this lesson?
Check yourself
Answer the questions from this lesson. Pick an answer to see right away whether it is correct.
1. What does SSR (Server-Side Rendering) mean?
2. What is hydration in the context of SSR?
These are 2 of 3 questions for this lesson. Solve the rest in the game.
Hands-on tasks in the game
- Code editor
Define a RenderStrategy union type and a StrategyInfo interface.
- Vertical ordering
Arrange the steps of the Server-Side Rendering process:
- Code editor
Define a CrewMember interface and type the data, pending, error states.
- Vertical ordering
Arrange the loading order in a SPA (Single Page Application):
- Click in order
Arrange rendering strategies from fastest to slowest First Contentful Paint:
- Code editor
Define a Page union type and type navigation between pages.