Skip to content

共享数据 sharedPrerenderData

Nuxt 3.10 带来了不少特性,其中一个对预渲染(prerender)、内容密集型(content-heavy)站点特别有用,那就是实验性的 sharedPrerenderData

预渲染指在构建阶段把页面提前渲染成静态 HTML。

问题在于:当很多页面都调用同一份数据(比如全站导航菜单、分类列表、作者信息、全局配置)时,每个页面在预渲染时都会各自重新请求一遍。页面数量一多,这些重复请求(duplicate calls)会成倍拖慢构建时间。

sharedPrerenderData 要解决的正是这个痛点:让基于相同 key 的数据在预渲染的不同页面之间共享,只获取一次,后续页面直接复用。

sharedPrerenderData 到底做了什么

核心机制可以概括为一句话:在预渲染期间,按 useAsyncData / useFetch 的 key 缓存数据,跨页面复用同一份结果。

Nuxt 中每次 useAsyncDatauseFetch 调用都对应一个 keyuseFetch 会根据请求 URL 等自动生成,useAsyncData 则由第一个参数显式指定)。

开启 sharedPrerenderData 后:

  • 第一个页面预渲染时,某个 key 的数据被真正获取并缓存;
  • 之后其它页面预渲染时,若遇到相同 key,直接取用缓存,不再重复请求

重复请求是怎么发生的

用一个简单 demo 演示问题:站点里多个页面都通过 useAsyncData 拉取同一份数据(例如公共列表)。

vue
<script setup lang="ts">
// 假设每个页面都会用到的公共数据
const { data: categories } = await useAsyncData(
  'categories',
  () => $fetch('/api/categories')
)
</script>

在预渲染时,如果站点有 100 个页面、每个页面都调用 useAsyncData('categories', ...),那么 /api/categories 就会被请求 100 次,尽管每次拿到的都是相同结果。

对于内容多、页面多的站点,这类冗余请求会明显拉长构建时间。

如何减少重复请求:开启 sharedPrerenderData

解决方式非常简单,在 nuxt.config 中开启对应的实验性选项:

ts
// nuxt.config.ts
export default defineNuxtConfig({
  experimental: {
    sharedPrerenderData: true
  }
})

开启后,预渲染阶段相同 key 的数据只会被获取一次,其余页面复用缓存结果。

对于前面 100 个页面共用 categories 的例子,/api/categories 理论上只需请求一次,构建时间随之下降。

关键前提:相同 key 必须对应相同数据

特别强调了一个重要前提(important prerequisite):既然共享是按 key 进行的,那么就必须保证:

同一个 key,在所有页面里都对应同一份数据。

这意味着 key 与数据之间要有稳定、可预测的对应关系。

如果你在不同页面里用了相同的 key,却期望它们返回不同的数据,开启 sharedPrerenderData 后就会出问题:后续页面会错误地复用第一个页面缓存的结果,导致数据串台。

典型的危险写法是:key 写死成通用名,但实际数据依赖路由参数。

vue
<script setup lang="ts">
const route = useRoute()

// ⚠️ 危险:key 固定为 'post',但数据随 id 变化
const { data } = await useAsyncData(
  'post',
  () => $fetch(`/api/posts/${route.params.id}`)
)
</script>

正确做法是让 key 随数据的区分维度一起变化:

vue
<script setup lang="ts">
const route = useRoute()

// ✅ key 包含 id,不同文章对应不同 key
const { data } = await useAsyncData(
  `post:${route.params.id}`,
  () => $fetch(`/api/posts/${route.params.id}`)
)

useFetch 会依据请求 URL 等自动生成 key,通常天然满足「相同 URL → 相同数据」。

useAsyncData 的 key 完全由你手动控制,因此手写 key 时更容易踩到「同 key 不同数据」的坑,这也是开启该特性前最需要审查的地方。

内部实现思路:Nuxt 在预渲染过程中维护一份跨页面的数据缓存,以 key 为索引。

当某个页面完成对某 key 的数据获取后,结果被存入这份共享缓存;后续页面在执行 useAsyncData / useFetch 前,会先检查缓存中是否已有该 key 的数据,命中则跳过实际请求直接返回。

这套机制只作用于预渲染阶段,目的是在构建期消除重复的数据获取,而不改变运行时(runtime)的行为。相关实现可参考对应的 Nuxt PR #24894

使用 sharedPrerenderData 的步骤

  1. 确认站点使用了预渲染,且存在多页面共用同一份数据的场景(导航、分类、全局配置等)。
  2. nuxt.config.tsexperimental 中设置 sharedPrerenderData: true
  3. 审查所有 useAsyncData 的 key:确保相同 key 一定对应相同数据
  4. 对依赖路由参数或动态输入的数据,把区分维度(如 id)拼进 key。
  5. 重新执行预渲染构建,观察重复请求数量与构建时间的下降。
  6. 若出现数据串台,优先排查是否存在「同 key 不同数据」的调用。

注意事项

事项说明
特性为实验性位于 experimental.sharedPrerenderData,需显式开启
仅作用于预渲染阶段目的是缩短构建时间,不改变运行时行为
共享按 key 进行相同 key 会复用同一份缓存数据
必须保证 key 与数据一致同 key 不同数据会导致后续页面拿到错误的缓存结果
useAsyncData key 需手动把控动态数据要把 id 等维度拼进 key
适合内容密集型站点页面越多、共用数据越多,收益越明显

sharedPrerenderData 的价值在于用一个开关消除预渲染阶段的冗余数据获取,但它把正确性的责任交给了开发者,只要守住「相同 key 对应相同数据」这条铁律,就能安全地换取更短的构建时间。