前端 SSR 实战:Nuxt 3 的 SEO 与 Hydration

2026年6月17日 blogTech 5 分钟阅读 4 次阅读
📖 文章摘要

Nuxt 3 SSR 在 SEO 和首屏性能上优势明显,但也带来了 hydration 匹配的挑战。本文详解数据获取策略、分页缓存和三个实际踩坑案例。

Nuxt 3 SSR 实战

本博客前端使用 Nuxt 3 的服务端渲染模式。SSR 的最大收益是 SEO——搜索引擎直接拿到完整 HTML,无需执行 JavaScript。

数据获取策略

Nuxt 3 提供了三个数据获取 composable:

<script setup>
// 1. useAsyncData — SSR 阶段执行,数据嵌入 HTML
const { data } = await useAsyncData('home', () =>
  get('/api/articles', { page: page.value, size: 24 }),
  { watch: [page] }
)

// 2. useLazyAsyncData — 客户端执行,不阻塞页面渲染
const { data: siteInfo } = useLazyAsyncData('site-info', () =>
  get('/api/site').catch(() => ({}))
)

// 3. useFetch — useAsyncData 的封装,自动处理 baseURL
const { data } = await useFetch('/api/articles')
</script>

区分 SSR 和客户端数据的标准

  • 首屏必须展示的内容 → useAsyncData(文章列表、文章详情)
  • 非关键的内容 → useLazyAsyncData(站点信息、作者资料)
  • 用户操作触发的内容 → 客户端手动 fetch(评论提交、搜索)

分页与数据刷新

useAsyncData 默认缓存 key 是固定的,当页面查询参数变化时不会自动刷新。解决办法是使用 watch 选项:

const { data } = await useAsyncData(
  'home',
  () => get('/api/articles', { page: page.value, size: 24 }),
  { watch: [page] }
)

watch: [page] 让 Nuxt 监听 page 这个 reactive ref,变化时自动重新执行查询函数并更新 UI。

组件自动导入

Nuxt 3 支持 components/ 目录下的组件自动导入,无需手动 import

// nuxt.config.ts
components: {
  dirs: [
    '~/components/base',   // 基础组件(GlassCard, Pagination...)
    '~/components/blog',   // 业务组件(ArticleCard, CommentSection...)
    '~/components/search',
    '~/components/admin',
  ],
},

模板中直接用 <GlassCard> 即可,Nuxt 按目录优先级查找。如果多个目录有同名组件,前面的目录优先。

Hydration 踩坑

Vue 3 的 hydration 机制要求 SSR 输出和客户端首次渲染的 DOM 完全一致。本博客遇到过的三个典型问题:

问题 1:`` 标签差异

症状Hydration children mismatch on <a>,导航栏中的 NuxtLink 报错。

根因:Vue Router 在客户端会 patch 所有带 href<a> 元素(拦截导航、绑定事件),导致 children 数量不一致。哪怕用了原生 <a :href="..."> 也是如此。

解决:用 <div @click="router.push()"> 替代 <a>

问题 2:动态 class/attribute 不一致

症状:空的 style="" 属性在 SSR 输出中不存在,但客户端渲染时会添加。

解决:把动态绑定移到父容器,子组件保持纯静态 HTML。

问题 3:条件渲染的 `v-if`

症状v-if 在 SSR 和客户端判断结果不同(如 sessionStorage 检查)。

解决:将客户端初始化逻辑放到 onMounted,SSR 阶段统一渲染为 false。

开发工具链

开发模式同时启动三个进程:

# 终端 1:后端 API
cd backend && uvicorn main:app --reload --port 8001

# 终端 2:前端 dev server
cd frontend && npm run dev  # 端口 3000

# 前端通过 Vite proxy 代理 API 请求到 8001

start.bat 脚本一键同时启动前后端。

SEO 配置

  • Nuxt SSR 直接输出 HTML,爬虫可完整抓取
  • public/robots.txt 允许所有爬虫
  • /api/sitemap.xml 动态生成站点地图
  • URL 使用 slug 而非 id(/p/redis-cache 优于 /p/42
  • 已提交 Google Search Console + Bing Webmaster Tools
最后更新:2026年6月29日CC BY-NC-SA 4.0

评论

暂无评论,来写第一条吧

© 2026 My Blog. Built with Nuxt.js + FastAPI.