组合式生命周期在SSR中无需避开浏览器专属钩子,因它们本就不执行;需谨慎处理的是setup及服务端可执行逻辑,须用环境判断避免访问window等API,并通过useAsyncData等机制保障首屏数据预取与hydration一致性。

组合式生命周期在 SSR 中不能直接避开浏览器专属钩子——它们本来就不会执行,关键在于别误用或依赖它们做服务端逻辑。
哪些组合式钩子根本不会在服务端运行
以下钩子只在客户端 hydration 后触发,服务端渲染阶段(renderToString / renderToNodeStream)完全不调用,无需“避开”,但也不能指望它们干活:
- onMounted:需要真实 DOM 挂载,服务端只有 HTML 字符串
- onUpdated:依赖响应式更新 + DOM 重绘,服务端无更新机制
- onBeforeMount、onBeforeUpdate、onUnmounted、onBeforeUnmount:同理,全部基于浏览器运行时环境
- onActivated、onDeactivated:keep-alive 行为仅存在于客户端
真正需要谨慎处理的是 setup 和服务端可执行钩子
setup() 是组件初始化必经入口,服务端和客户端都会执行。它替代了 beforeCreate 和 created,因此所有初始化代码(包括数据获取)默认在这里跑——必须主动判断环境:
递归分析 Vue 项目组件依赖,从入口文件生成组件层级图,支持 Vue 2/3,输出组件名、文件路径和属性。适用于分析组件结构、排查依赖或了解项目架构。
- 用 typeof window === 'undefined' 判断是否在服务端(通用方案)
- 在 Nuxt 中可用 process.server(更简洁)
- 避免在 setup 里直接访问
window、document、localStorage、navigator等 - 非确定性操作如
Date.now()、Math.random()应封装为可 SSR 友好的函数(例如取服务端传入的时间戳)
服务端专用数据预取:用对钩子才不踩坑
Vue 本身不提供服务端专用钩子,但框架层做了适配。安全获取首屏数据的推荐方式:
立即学习“前端免费学习笔记(深入)”;
- Nuxt 3 推荐使用 useAsyncData 或 asyncData:自动区分环境,服务端等待 Promise 完成后再渲染,客户端跳过重复请求
- Vue 2 + vue-server-renderer 可用 serverPrefetch(选项式 API),组合式中需配合插件或自定义逻辑
- 若手动在 setup 中发请求,务必包裹环境判断:
if (typeof window === 'undefined') { /* fetch data */ } - 数据获取后,确保注入到服务端上下文(如 Nuxt 的
context.payload或 Vue SSR 的context.state),供客户端 hydration 复用
hydration 一致性的硬要求
服务端生成的 HTML 和客户端首次渲染结果必须完全一致,否则会触发 Vue 警告甚至降级重渲染:
- 避免在服务端用随机值、本地时区时间、用户 UA 等生成不同 HTML
- store 状态必须在服务端预置并序列化到页面(如
window.__INITIAL_STATE__),客户端 hydrate 时直接读取 - 不要在 onMounted 里拉首屏核心数据——这等于放弃 SSR,用户看到白屏或内容闪动

















