SSR 客户端注水优化
客户端注水是将服务端渲染的静态 HTML 与客户端 JS 状态同步的过程。
注水问题
| 问题 | 表现 | |
|---|---|---|
| 重复渲染 | 注水后再次渲染 | |
| 状态丢失 | 服务端数据未同步 | |
| 性能下降 | 注水时间过长 |
注水原理
JavaScript
服务端渲染 HTML → 客户端加载 JS → 注水匹配 DOM → 绑定事件
避免重复渲染
JavaScript
// 正确的注水方式
import { createSSRApp } from 'vue'
const app = createSSRApp(App)
// 服务端已渲染,注水匹配现有 DOM
app.mount('#app', true) // true 表示注水而非新渲染
注意:注水时 Vue 匹配现有 DOM,不重新创建。
数据状态同步
vue
// 服务端预取数据
export async function serverPrefetch() {
const data = await fetchAPI()
// 数据注入到 window.__INITIAL_STATE__
return data
}
// 客户端同步状态
const initialState = window.__INITIAL_STATE__
const app = createSSRApp(App)
app.provide('initialState', initialState)
按需注水
JavaScript
<script setup>
import { ref, onMounted } from 'vue'
// 仅注水需要的组件
const hydrated = ref(false)
onMounted(() => {
// 延迟注水非关键组件
hydrated.value = true
})
</script>
注水性能优化
| 策略 | 效果 | |
|---|---|---|
| 数据预取 | 减少客户端请求 | |
| 增量注水 | 非关键组件延迟 | |
| 组件缓存 | 减少重复渲染 | |
| 状态共享 | 避免数据重复 |
增量注水示例
JavaScript
// Nuxt 增量注水配置
export default defineNuxtConfig({
experimental: {
// 增量静态生成
isr: true
}
})
注水失败处理
text
// 注水失败时重新渲染
try {
app.mount('#app', true)
} catch (e) {
// DOM 不匹配,重新渲染
document.getElementById('app').innerHTML = ''
app.mount('#app')
}
要点总结
- 注水匹配现有 DOM,不重新创建
- 服务端数据注入 window.INITIAL_STATE
- 按需注水减少非关键组件开销
- 注水失败时可重新渲染
📝 发现内容有误?点击此处直接编辑