跳转到内容

Nuxt — Vue 全栈框架

是什么

Nuxt 是 vue 生态的全栈框架——把”路由 / 服务端渲染 / 静态生成 / 自动 import / 部署”全部打包成开箱即用的约定。日常类比:next-jsreact 的酒店服务,Nuxt 是 Vue 的酒店服务——你写 <script setup> 就像办入住,路由表 / 数据获取 / 部署适配这些”行李房 / 前台 / 接送车”全都不用自己张罗。

你新建一个 pages/index.vue

<script setup>
const msg = ref("Hi from Nuxt")
</script>
<template>
<h1>{{ msg }}</h1>
</template>

文件保存的那一刻,浏览器访问 / 已经能渲染——没写一行路由配置、没手 import ref、没配 SSR。这三件事 Nuxt 都替你做了。

为什么重要

不理解 Nuxt,下面这些事都没法解释:

  • 为什么 Vue 项目从”自己拼 Vue Router + Pinia + Vite + 部署脚本”变成”装个 Nuxt 全有了”
  • 为什么同一份代码可以一键部署到 Node / Bun / Deno / Cloudflare Workers / Vercel Edge / Netlify——这是 Nitro 引擎做的事
  • 为什么 Nuxt 项目里 ref() / useFetch() / <MyButton /> 都不用 import 还能直接用——这是 auto-import
  • 为什么 @nuxt/image / @nuxt/content / @nuxt/auth-utils 装一行就跑——Nuxt 的官方模块系统比社区插件统一得多

Nuxt 的核心价值有三点:

  1. Vue 生态的全栈首选:要做 SSR / SSG / API 路由 / 同构数据获取,Nuxt 是 Vue 圈最完整的方案
  2. Nitro 让部署目标解耦:写一份代码,build 时通过 preset 切换部署目标——Node 服务器 / Cloudflare Workers / Vercel Edge / 静态文件夹任意切
  3. 约定大于配置pages/ 即路由、server/api/ 即接口、composables/ 自动可用——新项目省掉 80% 配置代码

核心要点

Nuxt 之所以能”少配置 + 同构 + 多部署目标”,靠 三个核心

  1. pages/ 目录约定路由

    • pages/index.vue/
    • pages/about.vue/about
    • pages/users/[id].vue/users/:id(动态参数)
    • pages/users/[id]/posts.vue/users/:id/posts(嵌套)
    • 不写一行 createRouter,文件结构就是路由表
  2. Nitro 服务端引擎

    • Nitro 是基于 H3(universal HTTP 框架)的服务端运行时——和 Express / Fastify 同位
    • 关键能力:写一份 defineEventHandler 代码,build 时通过 preset 编译到 Node / Bun / Workers / Deno / Edge——部署目标和源码解耦
    • 类比:写一份汉语稿,翻译机给你输出英 / 法 / 日 / 德版——Nitro 就是那台翻译机
  3. Auto-import(不用手写 import)

    • components/ 下的 Vue 组件:模板里 <MyButton /> 直接用
    • composables/ 下的函数:useUserStore() 直接调
    • utils/ 下的纯函数:直接当全局函数
    • Vue API:ref / computed / watch 自动 import
    • 类比:Java 的 java.lang.* 不用 import;Nuxt 把这套思路推到整个项目

实践案例

案例 1:最简一个文件就是首页

pages/index.vue

<script setup>
const msg = ref("Hi")
</script>
<template>
<h1>{{ msg }}</h1>
</template>

逐部分解释

  • <script setup> 是 Vue 3 的 Composition API 语法糖——里面声明的变量自动暴露到模板
  • ref("Hi") 创建一个响应式引用——没 import,Nuxt auto-import 自动加进去
  • pages/index.vue 这个文件位置就告诉 Nuxt”这是 / 的页面”——不用配路由
  • npx nuxi dev,浏览器访问 localhost:3000 直接看到 <h1>Hi</h1>——SSR 渲染,HTML 里就有内容(不是 SPA 那种白屏 + JS 注入)

案例 2:API 路由也是文件即接口

server/api/hello.ts

export default defineEventHandler(() => {
return { message: "Hello from API" }
})

逐部分解释

  • 文件位置 server/api/hello.ts → 接口 URL /api/hello
  • defineEventHandler 是 Nitro/H3 的接口声明函数——没 import,auto-import 处理掉
  • 返回 JSON 对象,Nitro 自动序列化 + 设置 Content-Type: application/json
  • 这个 API 部署到 Cloudflare Workers / Vercel Edge / Node 都不用改代码——Nitro preset 切换即可

案例 3:useFetch 同构数据获取

<script setup>
const { data } = await useFetch('/api/hello')
</script>
<template>
<pre>{{ data }}</pre>
</template>

为什么这个例子重要

  • useFetch服务端就把数据拉好——返回的 HTML 已经包含 <pre>{"message":"Hello..."}</pre>
  • 客户端 hydrate 时不再发起一次重复请求——payload 通过 <script> 注入到 window
  • 类比:next-jsgetServerSideProps + useEffect(fetch...) 二合一——一行 useFetch 搞定 SSR + CSR 两种场景

踩过的坑

  1. Nuxt 2 vs Nuxt 3 不兼容:Nuxt 2 基于 Vue 2 + Webpack,Nuxt 3(2022 末发布)基于 Vue 3 + Vite + Nitro——API、目录结构、生命周期几乎全换了。老项目升级近似重写。新项目直接 Nuxt 3+。

  2. Auto-import 让 IDE 跳转/类型提示要装官方插件:VS Code 默认看到 ref(0) 不知道这是 Vue 的 ref——必须装 Volar + @nuxt/typescript 才有跳转 / 自动补全 / 类型检查。新人常以为”代码能跑但 IDE 标红肯定哪里错了”——其实是插件没装。

  3. Server-only / Client-only 边界process.server / process.client 区分代码运行环境;useNuxtApp().payload 在两端含义不同。在 <script setup> 里直接用 localStorageSSR 阶段崩溃(服务器没有 localStorage)——必须包 if (import.meta.client) {...} 或用 <ClientOnly> 组件。

  4. Nitro preset 选错部署不通:build 时通过 nitro.preset = 'cloudflare' 切目标。如果代码里用了 Node 独有 API(如 fs.readFile),切到 Workers 会 build 失败但报错信息可能很绕——根因是 Workers runtime 没 fs 模块。

适用 vs 不适用场景

适用

  • Vue 生态的中大型 web app / 内容站 / SSR 需求
  • 需要”同一份代码部署到多个目标”的场景——Nitro preset 价值最大
  • 团队已熟悉 Vue,想要全栈但不想自己拼 Vue Router + Pinia + Nitro
  • API 后端轻量(CRUD / 调外部服务为主)——server/api/ 写起来比 Express 顺

不适用

  • 团队主用 React → 直接 next-js,Nuxt 没意义
  • 纯静态内容站(博客 / 文档)→ astro 默认 0 JS 更轻
  • 重型后端(复杂业务逻辑、长连接、worker 队列)→ Nitro 是轻量 HTTP 框架,不适合扛核心业务,建议另起 Node 后端
  • 完全前后端分离的 SPA → Vue + Vite 即可,Nuxt 的 SSR 能力用不上反成累赘

学到什么

  1. 约定大于配置 = 团队 90% 时间省在哪里:路由表 / 数据获取 / auto-import / 部署 preset——这些”约定”是 Nuxt 的核心交付物
  2. 同构(universal)的真意:同一份代码在服务器跑一次(生成 HTML)+ 浏览器跑一次(hydrate 接管)——useFetch 这类 API 的设计就是为了让作者不用关心代码到底在哪端跑
  3. 运行时和部署目标解耦:Nitro 是 Nuxt 最被低估的部分——它把”代码”和”跑在哪台服务器”分开,源码不变 preset 切换即换目标
  4. 生态完整性是 meta 框架的胜负手next-js / Nuxt / astro 的差别不是性能,而是”官方模块 + 默认值 + 文档”是否足够多到 90% 场景一行装一个就行

延伸阅读

关联

  • vue —— Nuxt 直接构建在 Vue 之上;理解 Vue Composition API 是用好 Nuxt 的前提
  • next-js —— React 生态的对应方案;理念相似(文件即路由 + SSR + auto-data-fetch),但运行时不通用
  • astro —— 另一种 meta 框架取舍:默认 0 JS、内容站优先;与 Nuxt 形成”内容 vs 全栈”的两端

反向链接

  • astro —— Astro — 内容站点优先的 Web 框架
  • next-js —— Next.js — React 全栈框架
  • react —— React UI 组件库
  • sveltekit —— SvelteKit — Svelte 全栈框架
  • unstorage —— unstorage — 让 KV 存储不绑死运行时的统一抽象层
  • vue —— Vue.js — 渐进式 UI 框架
  • vue-i18n —— vue-i18n — Vue 官方 i18n,切语言整页自己刷新