09 / 09

Payload Cache 到底缓存了什么?

理解 Payload 如何避免 Hydration 阶段重复请求,以及它和浏览器缓存的区别。

Payload Cache 到底缓存了什么?

学习目标

理解 Payload 是什么、为什么 Nuxt 第一次不会请求两次、Payload Cache 到底缓存了什么,以及它和浏览器缓存的区别。


一、这个知识解决什么问题?

上一章我们知道了 useFetch 不会触发两次请求。那么它是怎么做到的?

假设页面这样写:

const { data } = await useFetch('/api/user')

第一次访问时,服务器请求了一次 /api/user。浏览器拿到 HTML 后,Vue 又开始运行——浏览器是不是还会再请求一次?

如果,那服务器第一次请求不是白做了吗?

这就是 Payload 要解决的问题。


二、一起推导

服务器请求到 { name: "Steven", age: 30 },生成 <div>Steven</div>

如果浏览器再次发起请求,就是两次网络请求,效率太低。Nuxt 不会这样设计。

继续思考:服务器已经拿到了数据,为什么不一起发给浏览器?这样浏览器就不用再请求了。

于是,Payload 出现了


三、Payload 是什么?

除了 HTML,服务器还会把本次渲染过程中得到的数据,一起发送给浏览器:

SSR Response
├── HTML(用于显示首屏)
└── Payload(用于恢复 Nuxt 应用状态)

Payload 是 SSR 响应中额外携带的、可序列化的 Nuxt 状态快照

浏览器 Hydration 时发现数据已经存在,直接读取,不用再次请求接口。


四、脑图

Nuxt Payload Cache 脑图:按 key 传输并恢复 SSR 数据状态

整个过程的核心不是"记住某个 URL",而是 key 与数据的对应关系

payload.data[key] = serializableResult

服务端调用 useFetch 时,Nuxt 会生成 key 并将数据序列化到 Payload。客户端 Hydration 时,用相同 key 查找数据并恢复 datastatuserror 等响应式状态。

能够跨越服务器与浏览器边界的必须是可序列化数据。DOM 节点、函数、数据库连接、原始 Response 对象不应直接放入 Payload。


五、Payload 和浏览器缓存有什么区别?

浏览器缓存:缓存 HTTP Response(图片、CSS、JS),通用、长期、由浏览器管理。

Payload Cache:缓存 SSR 本次渲染的数据,服务于当前 SSR 页面与 Hydration 的状态交接,刷新页面就会重新生成。

两者完全不是一回事。


六、代码实验

创建:

<script setup>
const { data } = await useFetch('/api/time')
</script>

<template>{{ data }}</template>

打开 Chrome DevTools → Network,第一次进入页面,/api/time 通常只有一次真正的请求。浏览器 Hydration 阶段读取的是 Payload,不是再次请求服务器。


七、容易踩坑

❌ Payload 是浏览器缓存

不是。Payload 属于 Nuxt SSR 生命周期,不是 HTTP Cache。

❌ useFetch 只执行一次

不是。Server 和 Client 都会执行,只是 Client 读取的是 Payload,不会重复请求网络。

❌ Payload 永远存在

不是。刷新页面,重新 SSR,Payload 就会重新生成。


一句话记忆

Payload = SSR 数据快照,它让浏览器第一次 Hydration 不必重新请求接口。


系列完结

至此,「Nuxt 深度解析」系列 9 章全部完成。你现在应该建立了一张完整的 Nuxt 心智地图:

Browser 第一次访问
   Nuxt Server
   ├── 路由匹配(File-based Routing)
   ├── 执行 Vue 组件(Auto Import 补全依赖)
   │   └── useFetch() 请求数据,存入 Payload
   └── 返回 HTML + Payload
       Browser 显示 HTML(用户立即看到首屏)
       Hydration(Vue 接管 DOM,用 Payload 恢复状态)
       onMounted()(此时才能安全访问 window)
       正常的 Vue 应用运行