Nuxt.js 服务端渲染:SSR、SSG 与模块生态

FreeGuideOnline 最新 2026-06-15

Nuxt.js 服务端渲染:SSR、SSG 与模块生态

什么是 Nuxt.js 及其渲染模式

Nuxt.js 是一个基于 Vue.js 的渐进式框架,专为构建现代 Web 应用而设计。它内置了对服务端渲染(SSR)的支持,同时提供静态站点生成(SSG)和多种混合渲染模式,让你能根据项目需求灵活选择渲染策略。

Nuxt.js 的核心渲染模式包括:

  • SPA(单页应用):仅在客户端渲染,没有服务端预先输出 HTML。
  • SSR(服务端渲染):每次请求时在服务端生成完整的 HTML 页面,提高首屏加载速度和 SEO 表现。
  • SSG(静态站点生成):在构建时预渲染所有页面,输出静态 HTML 文件,适合内容不变的站点。
  • ISR(增量静态再生):在 SSG 基础上支持按需重新生成单个页面,兼顾静态优势与内容更新。

Nuxt 通过 nuxt.config.ts 中的 ssr 选项和 target 选项控制渲染模式,现代 Nuxt 3 则更统一地通过模块与路由规则实现。

快速上手 SSR 项目

创建项目并启用 SSR

使用推荐方式快速初始化一个 Nuxt 3 项目:

npx nuxi@latest init my-nuxt-app
cd my-nuxt-app

默认情况下,Nuxt 3 的 SSR 是开启的。打开 nuxt.config.ts,确认配置:

// nuxt.config.ts
export default defineNuxtConfig({
  ssr: true, // 默认即为 true,表示启用服务端渲染
})

此时运行 npm run dev,应用将在服务端渲染模式下工作。查看页面源代码,你会看到完整的 HTML 内容,而不仅仅是空白的 <div id="__nuxt"></div>

创建第一个 SSR 页面

pages 目录下创建 index.vue

<template>
  <div>
    <h1>Nuxt SSR 示例</h1>
    <p>当前服务器时间{{ serverTime }}</p>
    <p>当前客户端时间{{ clientTime }}</p>
  </div>
</template>

<script setup>
// 服务端执行
const serverTime = ref(new Date().toISOString())

// 客户端执行,通过 onMounted 确保仅在浏览器中更新
const clientTime = ref('')
onMounted(() => {
  clientTime.value = new Date().toISOString()
})
</script>

通过这段代码可以直观感受 SSR 与客户端激活的区别:serverTime 在服务端渲染时确定,随后在客户端激活时保持不变(除非手动更新),而 clientTime 只在客户端挂载后设置。

使用 useAsyncData 获取数据

在 SSR 模式下,数据获取需要同时考虑服务端和客户端。Nuxt 提供 useAsyncDatauseFetch 等组合式函数来处理异步数据:

<script setup>
const { data: posts } = await useAsyncData('posts', () =>
  $fetch('https://jsonplaceholder.typicode.com/posts')
)
</script>

useAsyncData 会在服务端预取数据,并将结果序列化传递到客户端,避免重复请求。它的第一个参数是唯一键,用于缓存和 hydrate。更简洁的方式是使用 useFetch

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

深入理解服务端渲染(SSR)

SSR 工作流程

  1. 请求到达:用户通过浏览器请求一个页面。
  2. 服务端渲染:Nuxt 在 Node.js 环境中执行 Vue 组件,生成 HTML 字符串,并将组件状态(如 useAsyncData 的数据)序列化后嵌入到 <script> 标签中。
  3. 返回完整 HTML:客户端收到包含实际内容的 HTML,可以立即展示首屏。
  4. 客户端激活(Hydration):浏览器加载 JavaScript 后,Vue 会接管静态 HTML,将其变为可交互的响应式应用。这一过程会复用已有的 DOM,并附着事件监听器。

这种模式的优势是:首屏加载快速,对搜索引擎友好,同时保留了 Vue 的响应式交互能力。

处理仅在客户端运行的代码

由于 SSR 阶段没有浏览器 API(如 windowdocument),你需要妥善处理仅限客户端的代码:

  • 使用 process.client 判断
    if (process.client) {
      // 仅在浏览器执行
    }
    
  • 利用 <ClientOnly> 组件
    <ClientOnly>
      <SomeBrowserOnlyComponent />
    </ClientOnly>
    
  • onMounted 中执行:所有 onMounted 钩子只会在客户端运行。

错误处理与中间件

Nuxt 提供了全局错误处理页面 error.vue,以及路由中间件(middleware)来做权限验证或重定向。中间件支持服务端或客户端执行,通过 defineNuxtRouteMiddleware 定义:

// middleware/auth.ts
export default defineNuxtRouteMiddleware((to, from) => {
  if (!isAuthenticated()) {
    return navigateTo('/login')
  }
})

在 SSR 场景下,中间件会在服务端首次运行时被调用,可以控制页面的初始渲染。

静态站点生成(SSG)

启用完全静态生成

如果项目的所有内容在构建时就已经确定,你可以配置为完全静态生成模式:

nuxt.config.ts 中设置:

export default defineNuxtConfig({
  ssr: true,
  nitro: {
    prerender: {
      routes: ['/', '/about'], // 手动指定需要预渲染的路由
      crawlLinks: true         // 自动爬取页面内的链接并预渲染
    }
  }
})

构建时运行:

npx nuxi generate

这将在 .output/public 目录下生成静态 HTML 文件,可以部署到任何静态托管服务(如 Netlify、Vercel、Cloudflare Pages)。

混合渲染:按路由选择模式

Nuxt 支持在同一项目内对不同路由使用不同渲染策略。可以使用 routeRules 精细控制:

export default defineNuxtConfig({
  routeRules: {
    // 首页使用 SSR
    '/': { ssr: true },
    // 博客文章使用 SSG,在构建时生成
    '/blog/**': { static: true },
    // 管理后台完全使用客户端渲染(SPA)
    '/admin/**': { ssr: false },
    // 特定动态路由使用 ISR,60 秒后重新验证
    '/products/**': { isr: 60 }
  }
})

这种混合模式让你能在一个应用内同时享受 SSR 的实时性、SSG 的高性能和 SPA 的交互体验。

Nuxt 模块生态:快速增强 SSR 能力

Nuxt 拥有丰富的模块系统,可以零配置集成各种功能,同时完美适配 SSR 环境。

常用核心模块

  • @nuxt/image:优化图片加载,支持自动格式转换、响应式尺寸和懒加载。在 SSR 中自动生成占位符并优化图片路径。 安装:npm install @nuxt/image

    export default defineNuxtConfig({
      modules: ['@nuxt/image']
    })
    
  • @nuxtjs/i18n:国际化解决方案,支持 SSR 下的多语言路由和翻译加载。 安装:npm install @nuxtjs/i18n

    export default defineNuxtConfig({
      modules: ['@nuxtjs/i18n'],
      i18n: {
        locales: ['en', 'zh'],
        defaultLocale: 'en'
      }
    })
    
  • @nuxtjs/tailwindcss:集成 Tailwind CSS,在 SSR 构建时生成最小化样式。

    npx nuxi module add tailwindcss
    
  • @nuxtjs/color-mode:轻松实现暗黑模式切换,且兼容 SSR(避免闪烁)。

    npx nuxi module add color-mode
    

SEO 优化模块

  • @nuxtjs/seo(Nuxt 3):一站式 SEO 包,包含 @nuxtjs/html-validator@nuxtjs/sitemap 等。
  • @nuxtjs/robots:生成 robots.txt
  • nuxt-simple-sitemap:自动生成站点地图。

这些模块大多在 SSR/SSG 场景下自动生成必要的元标记和文件,确保搜索引擎能正确抓取和索引。

内容管理模块

  • @nuxt/content:基于文件的 CMS,可将 Markdown、YAML、CSV 等作为内容源。它天然支持 SSR 和 SSG,能配合查询 API 在构建时或请求时获取内容。

安装:

npx nuxi module add content

使用示例:

<script setup>
const { data: articles } = await useAsyncData('articles', () =>
  queryContent('/blog').find()
)
</script>

在 SSG 模式下,Nuxt 爬虫会自动发现内容路由并预渲染。

部署 SSR 应用

SSR 应用需要 Node.js 服务器环境。Nuxt 3 使用 Nitro 作为服务引擎,可以将应用部署到多种平台:

  • Node.js 服务器:构建后运行 node .output/server/index.mjs
  • 无服务器函数:Vercel、Netlify Functions、AWS Lambda 等
  • 边缘计算:Cloudflare Workers、Deno Deploy

生产构建命令:

npm run build

配置文件中的预设会影响部署方式。例如,部署到 Vercel 时,你几乎不需要额外配置,Vercel 会自动识别 Nuxt 项目并使用正确的预设。

常见问题与调试

避免内存泄漏

在 SSR 中,服务器实例会处理多个请求,务必避免使用全局单例状态。将具有状态的变量定义在 setup 函数或组合式函数内部,而不是模块顶层。

环境变量

Nuxt 中使用 useRuntimeConfig() 访问运行时配置,它可以安全地暴露给客户端或仅限服务端:

export default defineNuxtConfig({
  runtimeConfig: {
    // 只能服务端访问的密钥
    apiSecret: '',
    // 可暴露给客户端
    public: {
      apiBase: '/api'
    }
  }
})

调试服务端代码

可以使用 console.log 输出到终端,Nuxt 开发模式下服务端代码会显示在 Nuxt 命令行窗口。也可以使用 Node.js 调试器或 nuxt dev --inspect

总结

Nuxt.js 通过内置的 SSR、SSG 和灵活的混合渲染策略,让服务端渲染不再是复杂难题。配合强大的模块生态,你可以快速集成 SEO、图片优化、内容管理和国际化等功能。无论是构建内容型网站还是复杂交互应用,Nuxt 都能提供适合的渲染模式组合,平衡性能、开发体验和 SEO 需求。