Nuxt.js服务端渲染SSR #
一、SSR概述 #
服务端渲染(Server-Side Rendering)是在服务器端生成完整 HTML 页面的技术。Nuxt.js 默认使用 SSR 模式。
1.1 SSR优势 #
- SEO友好:搜索引擎可以抓取完整内容
- 首屏快速:用户更快看到页面内容
- 社交分享:Open Graph 标签正确渲染
- 渐进增强:支持禁用 JavaScript 的浏览器
1.2 SSR流程 #
text
用户请求
↓
服务器接收请求
↓
执行 Vue 组件
↓
生成 HTML
↓
发送到客户端
↓
客户端水合(Hydration)
↓
应用变为可交互
二、渲染模式 #
2.1 服务端渲染(SSR) #
默认模式,每次请求都在服务器生成 HTML。
typescript
export default defineNuxtConfig({
ssr: true
})
2.2 客户端渲染(CSR) #
仅在客户端渲染,适合不需要 SEO 的应用。
typescript
export default defineNuxtConfig({
ssr: false
})
2.3 混合渲染 #
页面级别选择渲染模式:
typescript
export default defineNuxtConfig({
routeRules: {
'/': { ssr: true },
'/admin/**': { ssr: false },
'/blog/**': { ssr: true }
}
})
2.4 页面级配置 #
vue
<script setup lang="ts">
definePageMeta({
ssr: false
})
</script>
三、数据获取 #
3.1 服务端数据获取 #
vue
<script setup lang="ts">
const { data } = await useFetch('/api/articles')
const { data: user } = await useAsyncData(
'user',
() => $fetch('/api/user')
)
</script>
3.2 仅客户端数据 #
vue
<script setup lang="ts">
const { data } = await useFetch('/api/user-preferences', {
server: false
})
</script>
3.3 仅服务端数据 #
vue
<script setup lang="ts">
const { data } = await useFetch('/api/internal', {
client: false
})
</script>
四、生命周期 #
4.1 服务端生命周期 #
vue
<script setup lang="ts">
if (import.meta.server) {
console.log('Running on server')
}
onServerPrefetch(async () => {
await fetchData()
})
</script>
4.2 客户端生命周期 #
vue
<script setup lang="ts">
onMounted(() => {
console.log('Component mounted on client')
})
onBeforeMount(() => {
console.log('Before mount on client')
})
</script>
4.3 通用生命周期 #
vue
<script setup lang="ts">
onCreated(() => {
console.log('Created on both server and client')
})
</script>
五、状态管理 #
5.1 状态共享 #
vue
<script setup lang="ts">
const state = useState('shared-state', () => ({
count: 0,
user: null
}))
</script>
5.2 状态水合 #
Nuxt 自动处理状态从服务端到客户端的传输。
vue
<script setup lang="ts">
const { data } = await useAsyncData('key', () => fetchData())
if (import.meta.server) {
state.value = serverState
}
</script>
5.3 避免水合不匹配 #
vue
<script setup lang="ts">
const mounted = ref(false)
onMounted(() => {
mounted.value = true
})
</script>
<template>
<div v-if="mounted">
Client-only content
</div>
</template>
六、ClientOnly组件 #
6.1 基本用法 #
vue
<template>
<ClientOnly>
<ClientSideComponent />
</ClientOnly>
</template>
6.2 降级内容 #
vue
<template>
<ClientOnly>
<HeavyChart />
<template #fallback>
<div>Loading chart...</div>
</template>
</ClientOnly>
</template>
6.3 条件渲染 #
vue
<script setup lang="ts">
const isClient = ref(false)
onMounted(() => {
isClient.value = true
})
</script>
<template>
<div v-if="isClient">
<ClientOnlyComponent />
</div>
</template>
七、环境检测 #
7.1 import.meta #
typescript
if (import.meta.server) {
console.log('Server environment')
}
if (import.meta.client) {
console.log('Client environment')
}
if (import.meta.dev) {
console.log('Development mode')
}
if (import.meta.prod) {
console.log('Production mode')
}
7.2 process #
typescript
if (process.server) {
console.log('Server')
}
if (process.client) {
console.log('Client')
}
7.3 useHydration #
vue
<script setup lang="ts">
const { data, error } = await useHydration(
'unique-key',
() => fetchOnServer(),
() => fetchOnClient()
)
</script>
八、常见问题 #
8.1 水合不匹配 #
原因:服务端和客户端渲染结果不一致
解决:
vue
<script setup lang="ts">
const date = ref('')
onMounted(() => {
date.value = new Date().toLocaleString()
})
</script>
8.2 window未定义 #
原因:服务端没有 window 对象
解决:
vue
<script setup lang="ts">
if (import.meta.client) {
console.log(window.location.href)
}
</script>
8.3 第三方库问题 #
vue
<script setup lang="ts">
let MyLibrary
onMounted(async () => {
MyLibrary = (await import('my-library')).default
})
</script>
九、性能优化 #
9.1 缓存策略 #
typescript
export default defineNuxtConfig({
routeRules: {
'/api/**': { cache: { maxAge: 60 } },
'/blog/**': { isr: 3600 }
}
})
9.2 流式渲染 #
vue
<script setup lang="ts">
const { data } = await useFetch('/api/data', {
lazy: true
})
</script>
9.3 预渲染 #
typescript
export default defineNuxtConfig({
nitro: {
prerender: {
routes: ['/', '/about', '/contact']
}
}
})
十、调试SSR #
10.1 服务端日志 #
vue
<script setup lang="ts">
if (import.meta.server) {
console.log('Server render:', useRoute().path)
}
</script>
10.2 客户端日志 #
vue
<script setup lang="ts">
onMounted(() => {
console.log('Client hydrated')
})
</script>
10.3 DevTools #
使用 Nuxt DevTools 查看 SSR 状态。
十一、最佳实践 #
11.1 数据获取 #
- 使用
useFetch和useAsyncData - 避免在
onMounted中获取 SSR 数据 - 使用
server: false排除不需要 SSR 的数据
11.2 组件设计 #
- 保持组件纯净
- 避免直接操作 DOM
- 使用
ClientOnly包装客户端组件
11.3 状态管理 #
- 使用
useState共享状态 - 避免在服务端使用客户端存储
- 正确处理状态水合
十二、总结 #
本章介绍了 Nuxt.js 服务端渲染:
- SSR 原理和优势
- 渲染模式选择
- 数据获取策略
- 生命周期处理
- 状态管理和水合
- 常见问题解决
- 性能优化技巧
SSR 是 Nuxt.js 的核心特性,下一章我们将学习静态站点生成。
最后更新:2026-03-28