← 返回内容列表
工程实践

Nuxt SSR 数据请求的边界

SSR 页面最常见的问题不是“能不能请求到数据”,而是同一段逻辑在服务端和浏览器中拥有不同上下文。

Nuxt SSRNuxt 3 数据请求useAsyncData服务端渲染Nuxt 水合错误SSR 数据获取

先用白话理解

这篇内容在讲什么?

SSR 是服务器先把页面内容生成好,再交给浏览器添加交互。

问题

Nuxt 水合报错,或者同一接口请求两次,怎样排查?

两端初始数据不同,或通用代码直接使用浏览器对象。

解决方案
  1. 公开数据使用 useAsyncData
  2. 浏览器 API 放到 onMounted
  3. 保持两端模板一致
  4. 避免重复请求
带状态的 SSR 请求示例代码
type Product = { id: number; name: string }

const { data, status, error, refresh } = await useAsyncData(
  'product-list',
  () => $fetch<Product[]>('/api/products'),
  { default: () => [] }
)

const products = computed(() => data.value ?? [])

onMounted(() => {
  // 只在浏览器中读取
  const savedView = localStorage.getItem('product-view')
})

// 模板中分别处理 status === 'pending'、error 和空数组
01

公开内容优先服务端获取

产品信息、文章内容和公开列表适合在服务端输出,提升首屏完整度和搜索可见性,同时避免客户端重复请求。

02

用户态数据需要隔离

Cookie、请求头和缓存不能跨用户复用。服务端请求必须从当前事件上下文读取身份信息,并谨慎设置共享缓存。

03

浏览器能力延后执行

localStorage、窗口尺寸和第三方交互库只能在客户端生命周期中使用。通过组件边界或延迟导入,可以避免水合不一致。

  • 服务端与客户端使用一致初始结构
  • 避免在模板渲染阶段读取窗口对象
  • 对客户端专属模块使用动态导入

结语

判断最终要回到真实体验

技术方案没有脱离场景的标准答案。把用户任务、业务边界、开发成本和长期维护放在一起评估,才有可能做出稳定、清晰且经得起变化的页面。

照着做的步骤

  1. 区分公开数据与登录数据
  2. 公开内容优先服务端获取
  3. 浏览器逻辑延后执行
  4. 保证两端初始结构一致

容易踩的坑

  • 服务端直接使用 window
  • 不同用户共享缓存
  • 服务端和浏览器输出不同内容

术语不用怕

  • SSR:服务器端渲染
  • 水合:浏览器接管服务器页面
  • 客户端:用户浏览器中的运行环境