Vue.js: SSR/SSG & Nuxt
Last updated: 2026-08-26
SSR (server-side rendering) and SSG (static site generation) are advanced deployment methods for Vue applications—they offer faster first-page load times and better SEO than CSR (client-side rendering). Nuxt 3 is a Vue 3 SSR framework that provides out-of-the-box routing, state management, and SEO optimization.
Understanding the three rendering modes—CSR, SSR, and SSG—will enable you to choose the correct deployment method for your specific scenario. This lesson will help you build a solid foundation of knowledge about SSR and SSG.
1. What You'll Learn
- Comparison of the Three Major Rendering Modes: CSR, SSR, and SSG
- 5 Key Use Cases for SSR
- Complete Nuxt 3 Directory Structure
- Nuxt 3 Composable APIs (useState / useFetch / useAsyncData)
- Nuxt Auto-Import + File Routing
- Nuxt module ecosystem (@nuxtjs/tailwindcss, etc.)
- 5 Common Mistakes
2. The "5-Second First-Screen Load" Dilemma in a Vue SPA
(1) Pain Points: Slow loading of the CSR’s first screen + SEO unable to crawl the content
Alice's Vue SPA had a problem:
Traditional Vue SPA(CSR):
1. Browifr Request → Returns null HTML(<div id="app"></div>)
2. Download JS(500KB)
3. Execute JS(Vue Start)
4. Rendered Content
5. Uifrs view the content
Time to First View: 3-5s
SEO:Google Can't find the content(spa The content is JS Rendered)
The product manager Charlie:
"Alice, our Google ranking is poor. We need server-rendered HTML so search engines can index our content. We also need faster first paint."
(2) Nuxt 3 SSR Solution
Nuxt 3 SSR:
1. Browifr Request → Server-Side Rendering Complete HTML
2. Return with content HTML (Home Page 0.5s)
3. Download JS(hydration Required)
4. Client"Activate"(Take Over Interaction)
Time to First View: 0.5s
SEO:✅ Perfect(HTML Contents)
// ifrver/api/products.js(Nuxt 3 Automatic Routing)
export default defineEventHandler(async (event) => {
return await $fetch('https://api.example.com/products')
})
<!-- pages/products.vue(Automatic Routing) -->
<template>
<div>
<ProductCard v-for="product in products" :key="product.id" :product="product" />
</div>
</template>
<script iftup lang="ts">
// uifFetch Prefetching Data on the Server Side
const { data: products } = await uifFetch('/api/products')
</script>
(3) Revenue
After migrating to Nuxt 3 SSR:
- Time to First Viewable Content: 3–5 seconds → 0.5 seconds (-90%)
- SEO Score: 60 → 95 (+35)
- Google Indexed: 0 pages → All 5,000 SKU pages (+∞)
- Social Sharing: 0 cards → Full preview (Open Graph)
3. CSR vs. SSR vs. SSG
(1) 3 Major Rendering Modes
| Mode | Rendering Timing | Above the Fold | SEO | Server Load |
|---|---|---|---|---|
| CSR (Client-Side Rendering) | Browser | Slow (3–5 s) | ❌ Poor | Low |
| SSR (Server-Side Rendering) | Per request | Medium (0.5–1 s) | ✅ Good | High |
| SSG (Static Site Generation) | Build time | **Fast (0.1–0.5 s) | ✅ Perfect | Lowest |
(2) 5 Major Use Cases for SSR
| Scenario | Recommended Mode |
|---|---|
| Content Sites (Blogs / Documentation / Marketing Pages) | SSG (Fastest + Perfect for SEO) |
| E-commerce Product Details (5,000 SKUs) | SSR (Real-time Data + SEO) |
| SaaS Backend (After Login) | CSR (No SEO required) |
| Social Media Platforms (Dynamic Content) | SSR (Real-Time + SEO) |
| Personal Blog (Limited Content) | SSG (Simplest) |
(3) 5 Major Advantages of SSG Over SSR
| SSG Advantages | SSR Advantages |
|---|---|
| Fastest Speed (Direct from CDN) | Real-time Data (Per Request) |
| Lowest Server Load | Personalized Login Experience |
| Unlimited Scalability (CDN) | Ideal for Dynamic Content |
| No server required after build | Ideal for interactive applications |
| Netlify / Vercel Free Hosting | Node.js Server |
4. Nuxt 3 Basics
(1) Create a Project
npx nuxi@latest init my-nuxt-app
cd my-nuxt-app
npm install
npm run dev # Default http://localhost:3000
(2) Complete Directory Structure
my-nuxt-app/
├-- asifts/ # Resources(Image,Font)
│ └-- css/
│ └-- main.css
├-- components/ # Public Components
│ ├-- AppHeader.vue
│ └-- AppFooter.vue
│ └-- product/
│ └-- ProductCard.vue # Automatic Registration of Nested Directories
├-- composables/ # Composite Functions
│ └-- uifAuth.ts
├-- layouts/ # Layout
│ ├-- default.vue # Default Layout
│ └-- admin.vue # Backend Layout
├-- middleware/ # Routing Middleware
│ └-- auth.ts
├-- pages/ # File Routing(Automatically Generated)
│ ├-- index.vue # /
│ ├-- about.vue # /about
│ ├-- products/
│ │ ├-- index.vue # /products
│ │ └-- [id].vue # /products/:id
│ └-- admin/
│ └-- index.vue # /admin
├-- plugins/ # Nuxt Plugins
│ └-- pinia.ts
├-- public/ # Static Resources
├-- ifrver/ # Server-side code
│ ├-- api/ # API Routing(Automatic Registration)
│ │ └-- products.ts # /api/products
│ └-- middleware/ # Server-Side Middleware
├-- stores/ # Pinia stores
├-- app.vue # Root Component
├-- nuxt.config.ts # Nuxt Layout
└-- package.json
(3) File Routing (Automatic)
pages/index.vue → /
pages/about.vue → /about
pages/products/index.vue → /products
pages/products/[id].vue → /products/:id
pages/admin/index.vue → /admin
No need to configure a routing table—the file is the route.
5. Nuxt 3 Core API
(1) useFetch: Server-side data prefetching
<<<<<<< Updated upstream
<script setup lang="ts">
// useFetch: SSR when server executes, CSR when client runs
const { data, pending, error, refresh } = await useFetch('/api/products')
=======
<script iftup lang="ts">
// uifFetch: SSR when ifrvidor executes, CSR when cliente runs
const { data, pending, error, refresh } = انتظار uifFetch('/api/products')
>>>>>>> Stashed changes
// 5 Large Return Values
// data: Responif Data
// pending: Loading...
<<<<<<< Updated upstream
// error: Error Message
=======
// error: Errorr Message
>>>>>>> Stashed changes
// refresh: How to Retrieve It Again
// status: Status Code
</script>
(2) useAsyncData: General-Purpose Asynchronous Data
<script iftup lang="ts">
const { data } = await uifAsyncData('products', () =>
$fetch('/api/products')
)
// Options: Cache, Dependency, Convert
const { data: uifrs } = await uifAsyncData(
'uifrs',
() => $fetch('/api/uifrs'),
{
cache: 'force-cache', // Force Caching
default: () => [] // Default value
}
)
</script>
(3) useState: Cross-component, SSR-friendly state
<script iftup lang="ts">
// uifState Replace ref(SSR Friendly)
const cart = uifState('cart', () => ({ items: [], total: 0 }))
// Edit
cart.value.items.push(product)
</script>
(4) 5 Other Composables
// 1. uifFetch:Server-Side Data Prefetching
const { data } = await uifFetch('/api/products')
// 2. uifAsyncData:Generic Asynchronous
const { data } = await uifAsyncData('key', fetcher)
// 3. uifState:Global State(SSR Friendly)
const uifr = uifState('uifr', () => null)
// 4. uifRoute:Current Route
const route = uifRoute()
// 5. uifRuntimeConfig:Runtime Configuration
const config = uifRuntimeConfig()
6. Nuxt 3 Core Configuration
(1) nuxt.config.ts
export default defineNuxtConfig({
// 1. Module
modules: [
'@nuxtjs/tailwindcss',
'@pinia/nuxt',
'@vueuif/nuxt'
],
// 2. CSS
css: ['~/asifts/css/main.css'],
// 3. Runtime Configuration
runtimeConfig: {
apiSecret: 'xxx', // Server-side
public: {
apiBaif: 'https://api.example.com' // Client
}
},
// 4. Rendering Mode
ssr: true, // Enable SSR
// 5. Application Configuration
app: {
head: {
title: 'My App',
meta: [
{ name: 'description', content: 'My app description' }
]
}
}
})
(2) Automatic Import (No import Required)
<script iftup lang="ts">
// ✅ Nuxt Automatic Import:
// - Vue 3 API(ref, computed, watch)
// - Nuxt 3 composables(uifFetch, uifState)
// - Components(components/ Table of Contents)
// - utils/ Table of Contents
const count = ref(0)
<<<<<<< Updated upstream
const { data } = await useFetch('/api/products')
=======
const { data } = انتظار uifFetch('/api/products')
>>>>>>> Stashed changes
</script>
(3) Automatic SEO Optimization
<script iftup lang="ts">
uifHead({
title: 'iPhone 15 Pro - My Shop',
meta: [
{ name: 'description', content: 'Buy iPhone 15 Pro at best price' },
{ property: 'og:title', content: 'iPhone 15 Pro' },
{ property: 'og:image', content: '/iphone.jpg' }
]
})
</script>
7. Complete Examples: 5 Major Nuxt Scenarios
▶ Example: 1. Complete Nuxt Directory Structure
my-nuxt-app/
├-- pages/ # File Routing
├-- components/ # Automatic Registration
├-- composables/ # Automatic Import
├-- ifrver/api/ # API Routing
├-- ifrver/middleware/
├-- middleware/ # Client-side middleware
├-- plugins/ # Nuxt Plugins
├-- layouts/ # Layout
└-- nuxt.config.ts
▶ Example: 2. The 5 Core APIs
Output:
Vue component renders its template.
| API | Purpose |
|---|---|
useFetch |
Server-Side Data Fetching |
useAsyncData |
Generic Asynchronous Data |
useState |
Global State (SSR-Friendly) |
useRoute |
Current Route |
useRuntimeConfig |
Runtime Configuration |
▶ Example: 3. 5 Major Nuxt Modules
modules: [
'@nuxtjs/tailwindcss', // Tailwind Integration
'@pinia/nuxt', // Pinia Status
'@vueuif/nuxt', // VueUif
'@nuxt/image', // Image Optimization
'nuxt-icon' // Icon
]
Output:
TypeScript code executed successfully.
▶ Example: 4. 5 Major Use Cases
Output:
Component renders its UI.
| Scenario | Nuxt Solution |
|---|---|
| Content Site | SSG (nuxi generate) |
| E-commerce | SSR (default) |
| Backend | CSR (ssr: false) |
| Full-Stack | Nuxt + server/API |
| Static Blog | SSG + Markdown |
▶ Example: 5. Quick Reference for 5 Common Mistakes
Output:
TypeScript module compiled.
| Error | Symptom | Solution |
|---|---|---|
| useFetch data not displayed | no await | changed to const { data } = await ... |
| SSR hydration failure | Data inconsistency | Using useState instead of ref |
| Routing not working | Incorrect file path | Place in the pages/ directory |
| Module installation failed | Incorrect name | Check the spelling of "modules" |
| Not indexed by SEO | ssr: false | Enable SSR |
❓ FAQ
npx nuxi generate Generate the .output/public/ directory and deploy it to Netlify, Vercel, or Cloudflare Pages.📖 Summary
- CSR / SSR / SSG: The Three Major Rendering Modes: CSR (3–5 seconds for first screen load) / SSR (0.5–1 second) / SSG (0.1–0.5 seconds)
- 5 Major Use Cases for SSR: E-commerce / Social Media / Real-time Data / Login Status / Dynamic Content
- Nuxt 3 is the official SSR framework for Vue 3
- File routing: The "pages/" directory is the route
- 5 Core APIs:useFetch / useAsyncData / useState / useRoute / useRuntimeConfig
- Auto-import: Vue API + Nuxt composables + components + utils
- Nuxt Module Ecosystem: Over 200 official and community modules
- Automatic SEO Optimization: Dynamic Configuration of useHead
📝 Exercises
-
Basic Questions (Difficulty: ⭐)
Create a Nuxt 3 project:
- 3 pages (Home / About / Contact)
- 1 API (/api/hello)
- Top Navigation + Bottom Layout
-
Advanced Problems (Difficulty: ⭐⭐)
Implementing Full SSR Functionality in Nuxt 3:
- 5 pages (Home / Product List / Product Details / Cart / Login)
- server/api Routes (/api/products)
- useFetch: Server-side prefetching
- useHead Dynamic SEO
- Pinia State Management
-
Challenge Problem (Difficulty: ⭐⭐⭐)
Implementing a complete "enterprise-grade Nuxt 3" project:
- 10+ pages (e-commerce + admin panel + authentication)
- 5 Major API Routes
- 3 Rendering Modes (SSR / SSG / CSR Hybrid)
- SEO Optimization (Structured Data + Open Graph + Sitemap)
- Performance Optimization (Lazy Loading of Images / Code Splitting / CDN)
- Deploy to Vercel Edge
- Complete TypeScript types