What Causes This Warning?
This warning appears when you try to use server components (.server.vue files) while having SSR disabled in your Nuxt configuration. Server components require server-side rendering to function.
The Problem
// nuxt.config.ts
export default defineNuxtConfig({
ssr: false, // SSR disabled
experimental: {
componentIslands: true // ❌ Conflict!
}
})
<!-- components/HeavyData.server.vue -->
<!-- ❌ Won't work with ssr: false -->
<template>
<div>Server-rendered content</div>
</template>
The Fix
Option 1: Enable SSR
// nuxt.config.ts
export default defineNuxtConfig({
ssr: true, // Enable SSR
experimental: {
componentIslands: true // ✅ Now works
}
})
Option 2: Don’t Use Server Components
// nuxt.config.ts
export default defineNuxtConfig({
ssr: false, // Keep SSR disabled
// Don't use componentIslands
})
Rename server components:
components/
├── HeavyData.server.vue → HeavyData.vue
└── Stats.server.vue → Stats.vue
Option 3: Use Route-Specific SSR
// nuxt.config.ts
export default defineNuxtConfig({
ssr: true, // Enable globally
routeRules: {
// Disable SSR only for specific routes
'/admin/**': { ssr: false },
'/dashboard/**': { ssr: false }
},
experimental: {
componentIslands: true
}
})
Understanding the Conflict
What Server Components Do
<!-- components/Data.server.vue -->
<script setup>
// This runs ONLY on the server
const data = await $fetch('https://api.example.com/heavy-data')
</script>
<template>
<!-- Rendered on server, sent as HTML -->
<div>{{ data }}</div>
</template>
Why ssr: false Breaks It
With ssr: false:
- No server-side rendering happens
- Everything runs in the browser
.server.vuefiles have nowhere to run
Alternative Patterns
For ssr: false Apps
Use client-side fetching instead:
<!-- components/Data.vue (not .server.vue) -->
<script setup>
// Fetches on client
const { data, pending } = await useFetch('/api/data')
</script>
<template>
<div v-if="pending">Loading...</div>
<div v-else>{{ data }}</div>
</template>
Lazy Loading Heavy Components
<!-- pages/index.vue -->
<template>
<!-- Lazy load without server components -->
<LazyHeavyChart v-if="showChart" />
</template>
<script setup>
const showChart = ref(false)
onMounted(() => {
// Load after initial render
showChart.value = true
})
</script>
Use ClientOnly Wrapper
<template>
<ClientOnly>
<HeavyComponent />
<template #fallback>
<LoadingSpinner />
</template>
</ClientOnly>
</template>
Hybrid Approach
Keep SSR but disable for specific pages:
<!-- pages/spa-page.vue -->
<script setup>
// This page is SPA-only
definePageMeta({
ssr: false
})
</script>
<template>
<!-- Client-side only content -->
<div>This page doesn't use SSR</div>
</template>
Server components work on other pages:
<!-- pages/ssr-page.vue -->
<template>
<!-- Server components work here -->
<HeavyData /> <!-- .server.vue component -->
</template>
When to Use Each Approach
| Approach | Use Case |
|---|---|
ssr: true + server components | Full SSR with optimized islands |
ssr: false (SPA) | Admin dashboards, apps behind auth |
| Route-specific SSR | Mixed public/private pages |
Migration Guide
From SPA to Hybrid
// nuxt.config.ts
export default defineNuxtConfig({
// Step 1: Enable SSR globally
ssr: true,
// Step 2: Disable for existing SPA routes
routeRules: {
'/app/**': { ssr: false }
}
// Step 3: Add server components gradually
// experimental: { componentIslands: true }
})
Quick Checklist
- Server components require
ssr: true - Don’t use
.server.vuewithssr: false - Use route rules for selective SSR
- Consider hybrid approach for mixed needs
- Rename
.server.vuefiles if not using SSR - Use
ClientOnlyfor client-specific components