Nuxt.js 完全指南:Vue 全栈框架的 SSR、SSG、API 路由与部署实践

Nuxt.js 3 深度实践:文件系统路由、SSR/SSG/ISR 渲染模式、API 路由(Server Routes)、useFetch/useAsyncData 数据获取、中间件与插件、SEO 与 Meta 管理、Nitro 服务端引擎、自动导入、部署到 Vercel/Netlify/Node.js。

Nuxt.js 是基于 Vue 的全栈框架,提供文件系统路由、服务端渲染(SSR)、静态生成(SSG)、API 路由、自动导入等开箱即用的能力。Nuxt 3 基于 Nitro 服务端引擎,支持 multi-provider 部署(Node /Vercel /Netlify/Deno/Workers),是 Vue 生态构建生产级全栈应用的首选方案。


一、Nuxt 3 核心特性速览

特性说明
文件系统路由pages/index.vue → /,pages/users/[id].vue → /users/:id
渲染模式SSR(默认)、SSG(prerender)、CSR(spa)、ISR(混合)
API 路由server/api/*.ts → /api/*,直接写后端接口
自动导入组件/Composables/工具函数无需 import
Nitro 引擎统一服务端运行时,支持 15+ 部署目标
TypeScript原生支持,类型自动生成
Module 生态300+ 官方和社区模块

二、文件系统路由

2.1 基础路由

pages/
├── index.vue           # /
├── about.vue           # /about
└── users/
    ├── index.vue       # /users
    └── [id].vue        # /users/:id

2.2 动态路由

<!-- pages/users/[id].vue -->
<script setup>
const route = useRoute()
const { data: user } = await useFetch(`/api/users/${route.params.id}`)
</script>

<template>
  <div>
    <h1>{{ user?.name }}</h1>
  </div>
</template>

2.3 嵌套路由

pages/
├── parent.vue          # 父布局(必须有 <NuxtPage />)
└── parent/
    ├── child.vue       # /parent/child
    └── index.vue       # /parent

三、数据获取

3.1 useFetch:SSR 友好的数据获取

<script setup>
// 服务端 + 客户端都能正确 hydration
const { data: posts, pending, error, refresh } = await useFetch('/api/posts', {
  lazy: false,           // 阻塞渲染(默认)
  server: true,          // 服务端获取
  default: () => [],     // 默认值
})

// 手动刷新
const handleRefresh = () => refresh()
</script>

3.2 useAsyncData:更精细控制

<script setup>
const { data, pending } = await useAsyncData('posts', () =>
  $fetch('/api/posts')
)
</script>

3.3 API 路由

// server/api/posts.get.ts
export default defineEventHandler(async (event) => {
  const query = getQuery(event)  // 读取查询参数
  const posts = await fetchPosts(query.limit)
  return posts
})

// server/api/posts.post.ts
export default defineEventHandler(async (event) => {
  const body = await readBody(event)
  const post = await createPost(body)
  return post
})

四、渲染模式

模式配置特点
SSR(默认)无需配置首屏快,服务端渲染
SSGnuxt generate预渲染为静态 HTML,CDN 友好
CSRssr: false纯客户端,SPA 体验
ISRrouteRules增量静态再生,按需更新
HybridrouteRules不同路由不同渲染模式
// nuxt.config.ts
export default defineNuxtConfig({
  routeRules: {
    '/': { prerender: true },           // 首页静态生成
    '/blog/**': { isr: 60 },            // ISR,60 秒重新验证
    '/admin/**': { ssr: false },        // 管理后台纯 CSR
    '/api/**': { cors: true },          // API 路由允许跨域
  },
})

五、中间件与插件

5.1 路由中间件

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

// pages/dashboard.vue
<script setup>
definePageMeta({
  middleware: ['auth'],
})
</script>

5.2 服务端插件

// server/plugins/auth.ts
export default defineNitroPlugin((nitroApp) => {
  nitroApp.hooks.hook('request', (event) => {
    // 每个请求都执行
    const token = getHeader(event, 'authorization')
    event.context.auth = parseToken(token)
  })
})

六、部署

6.1 Vercel

npx nuxi build  # 自动识别 Nitro preset

6.2 Node.js 服务器

npx nuxi build
node .output/server/index.mjs

七、Nuxt Module 开发与发布

Nuxt 的模块生态是其最强大的竞争力之一,官方与社区共贡献了超过三百个模块。除了使用现成模块,开发者也可以创建自定义模块来封装可复用的配置、插件、组件和组合式函数,从而在多个项目间复用基础设施。自定义模块通过 defineNuxtModule 定义,在安装时可以注册生命周期钩子、添加运行时模板、注入自动导入的组合式函数,甚至动态生成服务端文件,从而将通用逻辑沉淀为可共享的代码资产。

创建模块时,推荐在 modules/ 目录中新建子目录,并以 index.ts 作为入口文件。模块的核心生命周期是 setup 函数,开发者可以在其中访问 nuxt.options、使用 addPlugin 注册客户端或服务端插件、addComponentsDir 添加自定义组件目录、addImports 注入全局可用的组合式函数、addServerHandler 注册额外的服务端接口。这些能力使得模块不仅是配置打包器,更是功能完整的可插拔单元。

// modules/my-module/index.ts
import { defineNuxtModule, addPlugin, createResolver, addImports } from '@nuxt/kit'

export default defineNuxtModule({
  meta: { name: 'my-module', configKey: 'myModule' },
  defaults: { prefix: 'My' },
  setup(options, nuxt) {
    const resolver = createResolver(import.meta.url)
    // 注册客户端插件
    addPlugin(resolver.resolve('./runtime/plugin.ts'))
    // 注入自动导入的组合式函数
    addImports([
      { name: 'useMyFeature', as: 'useMyFeature', from: resolver.resolve('./runtime/composables') },
    ])
    // 为 nuxt.options.css 添加全局样式
    nuxt.options.css.push(resolver.resolve('./runtime/styles.css'))
  },
})

发布模块到 npm 后,用户只需在 nuxt.config.ts 的 modules 数组中引用包名即可自动完成安装。对于大型团队或长期维护的多项目架构,更推荐将模块放在 monorepo 的 packages/ 目录中统一管理,借助 pnpm workspace 或 Turborepo 实现跨项目共享组件库、工具函数和业务配置,从而大幅降低重复代码和维护成本。


八、SEO 与 Meta 管理进阶

现代 Web 应用对搜索引擎优化有极高要求。Nuxt 3 提供了 useSeoMeta 和 useHead 两个核心组合式函数来管理页面的标题、描述、Open Graph 和 Twitter Card 等元数据。与直接在模板中写 <meta> 标签不同,这些 API 能够在服务端渲染时正确注入到 HTML 的 <head> 中,保证搜索引擎爬虫获取完整的信息,从根上解决纯客户端动态渲染对 SEO 的不利影响。

结构化数据(JSON-LD)是提升搜索排名与被搜录概率的另一利器。通过在 useHead 中添加 script 元素并设置 type: 'application/ld+json',可以将文章、产品、面包屑导航等语义化结构信息直接嵌入 HTML。Nuxt 还支持通过 nuxt.config.ts 的 app.head 配置全局默认的 meta 标签,减少每个页面重复声明相同内容。同时 sitemap 的自动生成可以通过 @nuxtjs/sitemap 模块实现,Nuxt 会在构建阶段扫描所有路由并输出 sitemap.xml,并支持自定义更新频率和优先级参数,从而大幅提升搜索引擎的收录效率与内容发现速度。

<script setup>
useSeoMeta({
  title: 'Nuxt.js 完全指南',
  description: 'Nuxt 3 深度实践:SSR、SSG、API 路由与部署',
  ogTitle: 'Nuxt.js 完全指南',
  ogDescription: 'Nuxt 3 深度实践指南',
  ogImage: '/cover.png',
  twitterCard: 'summary_large_image',
})

useHead({
  script: [
    {
      type: 'application/ld+json',
      innerHTML: JSON.stringify({
        '@context': 'https://schema.org',
        '@type': 'TechArticle',
        headline: 'Nuxt.js 完全指南',
        author: { '@type': 'Person', name: 'Leeting Yan' },
      }),
    },
  ],
})
</script>

对于需要动态路由 SEO 的场景,例如博客文章页 /blog/[slug],可以在 useSeoMeta 中直接引用 useRoute() 获取的 params.slug,结合 useAsyncData 查询到的文章标题和摘要,实现每篇文章独一无二的元信息。这种服务端预渲染的 SEO 策略是 Nuxt 相较于纯 CSR 方案的核心优势之一。


九、性能优化实战

生产环境的 Nuxt 应用必须进行系统性的性能优化。首先是 payload 减载策略:Nuxt 默认会将服务端获取的数据序列化后嵌入 HTML,随后配合客户端 hydration 还原组件状态。如果某些页面的数据量异常庞大,可以通过 useFetch 的 transform 选项裁剪非必要字段,或在 nuxt.config.ts 中开启 experimental.payloadExtraction 配置将 payload 提取为独立文件以减少 HTML 体积。这项优化对于移动端用户和低带宽环境尤为重要,能够显著降低首屏加载时间。

组件懒加载对于首屏渲染速度至关重要。Nuxt 内置的 <NuxtPage> 和 <ClientOnly> 已经覆盖了路由级别和客户端隔离的大部分场景,但在大型页面内部,开发者还可以使用 Vue 的 defineAsyncComponent 或 Nuxt 文件路由的 lazy 前缀进一步拆分代码块。图片优化方面,推荐集成 @nuxt/image 模块,它能够自动适配多种响应式尺寸、支持现代 WebP 和 AVIF 格式转换、提供模糊占位图,并与 Vercel 和 Netlify 等主流平台的图片分发网络无缝集成,从而在视觉质量与传输体积之间取得最佳平衡。

<script setup>
const AsyncChart = defineAsyncComponent(() => import('~/components/HeavyChart.vue'))
const { data } = await useFetch('/api/dashboard', {
  transform: (res) => ({ stats: res.stats }), // 只保留必要数据
})
</script>

<template>
  <div>
    <NuxtImg
      src="/hero.png"
      sizes="100vw sm:50vw"
      format="webp"
      loading="lazy"
      placeholder
    />
    <AsyncChart v-if="data" :stats="data.stats" />
  </div>
</template>

SSR 缓存策略同样不可忽视。Nitro 支持通过 routeRules 配置 cache 选项,将页面响应缓存到 Redis 内存或本地文件系统中。合理设置最大存活时间和陈旧数据容忍时间,可以在保证内容新鲜度的同时大幅降低服务端的重复渲染压力。对于访问量极高的页面,还可以结合 CDN 边缘缓存实现全球节点级别的静态加速,这是达到毫秒级首屏响应的关键手段。


十、Auth 与中间件安全

全栈应用的安全体系建设是整个应用生命周期中不容忽视的关键环节。Nuxt 生态中的 nuxt-auth-utils 和 @sidebase/nuxt-auth 是主流的身份认证方案,支持 OAuth 协议、Credentials 凭据和 JWT 令牌等多种策略。认证模块通常被设计为服务端和客户端两部分协同工作:服务端负责 session 与会话管理、cookie 读取和 token 的签名校验,客户端则提供便捷的登录状态查询和用户信息的组合式函数,使得全栈认证逻辑浑然一体。

服务器中间件是鉴权体系的第一道防线。在 server/middleware/ 目录中放置的中间件会在所有接口请求到来之前顺序执行,非常适合统一处理跨域配置、CSRF 令牌校验和访问日志记录。对于涉及资金流转、权限变更等敏感操作,务必在路由处理函数内部进行二次校验,确保当前用户具有足够的角色权限,拒绝越权访问。

// server/middleware/auth.ts
export default defineEventHandler(async (event) => {
  if (event.path.startsWith('/api/admin')) {
    const session = await getUserSession(event)
    if (!session?.user?.role || session.user.role !== 'admin') {
      throw createError({ statusCode: 403, statusMessage: 'Forbidden' })
    }
  }
})

// server/api/login.post.ts
export default defineEventHandler(async (event) => {
  const body = await readBody(event)
  const user = await verifyCredentials(body.email, body.password)
  if (!user) {
    throw createError({ statusCode: 401, statusMessage: 'Unauthorized' })
  }
  await setUserSession(event, { user })
  return { success: true }
})

CSRF 防护方面,Nuxt 的 Nitro 运行时默认对同源请求提供基础保护。在跨域或第三方集成的场景下,应显式配置 routeRules 的 cors 选项,并通过服务端中间件验证请求头中的 CSRF 令牌是否与 session 中存储的值匹配。此外所有涉及身份凭证的敏感接口都必须强制启用 HTTPS 传输,防止中间人攻击窃取用户凭据和会话令牌,这是全栈安全不可逾越的底线。


常见问题(FAQ)

Nuxt 3 和 Nuxt 2 有什么区别?

  • Vue 3 + TypeScript 原生支持
  • Vite 替代 Webpack(开发速度提升 10 倍)
  • Nitro 替代 Nuxt 2 的服务端引擎
  • Composition API 默认
  • 自动导入所有内容

Nuxt 和 Next.js 怎么选?

  • Vue 生态 → Nuxt
  • React 生态 → Next.js
  • 两者功能对等,生态决定选择

相关阅读

  • Vue 详解 — Vue 3 核心概念
  • Vue Router 完全指南 — Nuxt 文件系统路由对比
  • Vue 状态管理指南 — Pinia 在 Nuxt 中的 SSR 兼容
  • Next.js 专题 — React 全栈框架对比
  • Vercel 专题 — Nuxt 部署到 Vercel
  • https://plumephp.com/vue-composition-api/ — 组合式 API 高阶用法与最佳实践
  • https://plumephp.com/vue-state-management/ — Pinia 状态管理深度指南
  • https://plumephp.com/vue-router-guide/ — Vue Router 导航守卫与动态路由
  • https://plumephp.com/vue-performance-optimization/ — Vue 渲染性能优化策略
  • https://plumephp.com/vercel-deploy-vue-nuxt/ — Vue 与 Nuxt 部署到 Vercel 的完整流程
  • https://plumephp.com/vue-testing-guide/ — Vue 单元测试与端到端测试体系建设

进阶路线图

掌握 Nuxt 基础后,建议按以下路线持续深化,构建系统性的全栈能力:

  1. 先打牢 Vue 核心基础:阅读 https://plumephp.com/vue-composition-api/,掌握组合式 API 的响应式原理、生命周期和最佳实践,这是 Nuxt 开发不可或缺的语法基础。
  2. 深入状态管理:结合 https://plumephp.com/vue-state-management/ 深入理解 Pinia 的 store 设计模式、服务端数据注入以及 SSR 场景下的状态同步策略,避免 hydration 不匹配问题。
  3. 打通路由认知:研读 https://plumephp.com/vue-router-guide/,掌握 Vue Router 的导航守卫、滚动行为与动态路由匹配,与 Nuxt 文件系统路由形成互补的认知框架。
  4. 关注通用优化:参考 https://plumephp.com/vue-performance-optimization/ 中的 Vue 通用渲染优化策略,包括虚拟列表、组件冻结和渲染函数技巧,将性能意识融入日常开发。
  5. 掌握部署实践:结合 https://plumephp.com/vercel-deploy-vue-nuxt/ 所学,将 Nuxt 应用平滑部署到 Vercel 或自建 Node 服务器,配置自定义域名与 CI/CD 流水线。
  6. 建立质量体系:最后通过 https://plumephp.com/vue-testing-guide/ 建立覆盖单元测试、组件测试和端到端测试的完整质量保障体系,为生产环境保驾护航。

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「frontend」更多文章

  1. GraphQL BFF 与微前端:多前端团队的 Schema 分片与协作模式
  2. 前端 GraphQL 客户端集成:Apollo Client、Relay 与 urql 选型
  3. 前端性能调试实战:从首屏加载到运行时瓶颈