Vue SSR初始状态加载核心是服务端HTML与客户端store状态一致,需服务端预取数据注入store、客户端从window.__INITIAL_STATE__恢复,并为每次请求创建独立store实例。

Vue 应用在 SSR 场景下,初始状态加载的核心是保证服务端渲染出的 HTML 与客户端挂载时的 store 状态完全一致,否则会触发 hydration 失败,页面出现闪动或逻辑错乱。
服务端预取数据并注入 Store
在服务端,不能等到组件挂载后再拉数据。必须在渲染前就完成数据获取,并把结果写入 store:
- 路由匹配后,遍历当前路由对应组件的
asyncData或fetch钩子(或统一定义的serverPrefetch) - 调用 store 的 action(如
store.dispatch('user/fetchProfile', id)),该 action 返回 Promise - 等待所有预取 Promise 完成,再执行
renderer.renderToString() - 将 store 当前 state 序列化为 JSON,内联到 HTML 的
<script>标签中(例如window.__INITIAL_STATE__ = {...})
客户端从 HTML 恢复 Store 状态
客户端初始化时,不能直接 new 一个空 store,而要优先读取服务端注入的状态:
- 在
entry-client.js中,先检查window.__INITIAL_STATE__是否存在 - 创建 store 实例时,将该对象作为初始 state 传入(Vuex:
new Vuex.Store({ state: window.__INITIAL_STATE__ || initialState });Pinia:通过pinia.state.value = window.__INITIAL_STATE__或插件方式恢复) - 确保 store 创建早于 Vue 实例挂载,且 router 和 store 同步(
sync(store, router))
避免状态污染与内存泄漏
每个请求必须使用独立的 store 实例,不能复用全局单例:
立即学习“前端免费学习笔记(深入)”;
- 服务端入口(
entry-server.js)导出的是工厂函数createStore(),而非实例 - 每次 HTTP 请求都调用一次
createStore(),保证状态隔离 - 客户端 store 不应保留服务端未序列化的响应式引用(如函数、Promise、DOM 节点),只保留可 JSON 序列化的纯数据
简化同步的推荐做法
对于新项目,建议优先选用 Pinia:
- 天然支持服务端状态序列化(
store.$state可直接赋值/读取) - 无需手动管理命名空间或模块注册,模块即组合式函数
- 配合
@pinia/nuxt或vueuse/core的useSSRStore工具,能自动处理 hydration 流程


















