Skip to content

Nuxt 系统学习文档 ​

适合人群:已经学过 Vue 基础,准备从“组件开发”进入“完整应用开发”的前端学习者

学习目标:从 Nuxt 入门到 SSR、数据获取、服务端能力、部署思路


目录 ​

  1. Nuxt 是什么
  2. 学习 Nuxt 前你应该先会什么
  3. 为什么很多 Vue 项目会选 Nuxt
  4. Nuxt 的渲染模式先搞明白
  5. 快速开始
  6. 项目目录结构怎么读
  7. 页面、路由、布局
  8. 数据获取:useFetch、useAsyncData、$fetch
  9. 状态管理与组合式能力
  10. 服务端能力与 Nitro
  11. SEO、Meta 与首屏体验
  12. 插件、中间件、模块
  13. TypeScript 在 Nuxt 中怎么用
  14. 部署、预渲染与上线思路
  15. 进阶主题
  16. 初学者高频踩坑点
  17. 推荐学习顺序
  18. 学习资源

1. Nuxt 是什么 ​

Nuxt 是基于 Vue 的全栈框架。

这句话一定要拆开理解:

  • 基于 Vue:你仍然在写 Vue 组件
  • 全栈框架:它不只帮你写页面,还帮你处理路由、服务端渲染、服务端接口、SEO、部署形态等问题

可以把它理解成:

“在 Vue 之上,帮你把一整个应用级方案搭好”


2. 学习 Nuxt 前你应该先会什么 ​

建议先掌握这些内容:

  • Vue 基础语法
  • 组件通信
  • Vue Router 的基本概念
  • Composition API
  • 基础异步请求
  • 基础 Node.js / npm 命令

如果 Vue 还不熟,就直接上 Nuxt,容易把“框架能力”和“Vue 基础”混在一起。


3. 为什么很多 Vue 项目会选 Nuxt ​

3.1 约定优于配置 ​

Nuxt 很多能力不需要你从零拼装。

例如:

  • pages/ 自动生成路由
  • layouts/ 定义布局
  • server/api/ 定义服务端接口
  • composables/ 自动导入

这能让你更快聚焦业务。

3.2 SSR 与 SEO 友好 ​

如果你做的是:

  • 内容站
  • 官网
  • 博客
  • 营销页
  • 首屏性能敏感页面

Nuxt 的优势会更明显。

3.3 服务端能力内建 ​

Nuxt 不只是“前端页面框架”,它通过 Nitro 提供了服务端运行能力。

这意味着你可以在一个项目里同时写:

  • 页面
  • API 路由
  • 中间件
  • 预渲染配置

4. Nuxt 的渲染模式先搞明白 ​

这是 Nuxt 初学阶段最关键的认知点之一。

4.1 CSR ​

客户端渲染。页面主要在浏览器中完成渲染。

特点:

  • 前端交互灵活
  • 首屏内容可能晚一点出现

4.2 SSR ​

服务端渲染。服务端先生成 HTML,再返回浏览器。

特点:

  • 首屏更完整
  • SEO 更友好
  • 需要理解服务端与客户端执行差异

4.3 SSG / 预渲染 ​

构建时提前生成静态 HTML。

适合:

  • 文档站
  • 博客
  • 基本不依赖实时数据的页面

4.4 Hybrid / Route Rules ​

不同页面走不同策略。

比如:

  • 首页预渲染
  • 用户后台客户端渲染
  • 商品详情页 SSR

这正是 Nuxt 的强项之一。


5. 快速开始 ​

我在 2026-06-15 核对的 Nuxt 官方安装页中,当前建议使用 Node.js 20.x 或更新版本,并推荐活跃 LTS。

5.1 创建项目 ​

bash
npm create nuxt@latest my-nuxt-app

进入目录并启动:

bash
cd my-nuxt-app
npm install
npm run dev

通常访问:

text
http://localhost:3000

5.2 你会看到的关键文件 ​

text
my-nuxt-app/
├── app/
├── assets/
├── components/
├── composables/
├── layouts/
├── middleware/
├── pages/
├── plugins/
├── public/
├── server/
├── app.vue
├── nuxt.config.ts
└── package.json

6. 项目目录结构怎么读 ​

6.1 pages/ ​

文件式路由的核心目录。

例如:

text
pages/index.vue        -> /
pages/about.vue        -> /about
pages/users/[id].vue   -> /users/:id

6.2 layouts/ ​

定义页面骨架。

比如:

  • 默认布局
  • 管理后台布局
  • 营销页布局

6.3 components/ ​

放通用组件。Nuxt 通常支持自动导入组件,写起来很省心。

6.4 composables/ ​

放组合式逻辑,比如:

  • useAuth
  • useUser
  • useCart

6.5 server/ ​

Nuxt 的服务端能力目录,常见子目录:

  • server/api/
  • server/middleware/

这说明 Nuxt 不只是“前端页面框架”。

6.6 app/ 目录与配置文件 ​

除了 pages/、components/,Nuxt 还约定了一些「应用级」文件:

  • app.vue:应用根组件,相当于整个应用的入口外壳。
  • app/app.config.ts:用 defineAppConfig 暴露构建时确定的公共配置(如站点标题、主题开关)。
  • nuxt.config.ts:用 defineNuxtConfig 写框架级配置(模块、运行时配置、路由规则等)。

Nuxt 里有两种「配置」很容易混,务必分清:

配置定义位置读取方式能否被环境变量覆盖时机
runtimeConfignuxt.config.tsuseRuntimeConfig()能(NUXT_ 前缀)运行时
app.configapp/app.config.tsuseAppConfig()不能构建时

runtimeConfig 分两层:

ts
export default defineNuxtConfig({
  runtimeConfig: {
    apiSecret: '默认值',        // 只在服务端可用(私密)
    public: {
      apiBase: '/api',          // 服务端 + 客户端都可用
    },
  },
})
  • runtimeConfig.apiSecret 这种非 public 的 key 只在服务端可读,不会泄漏到浏览器。
  • runtimeConfig.public.apiBase 会被打进每个页面 payload,客户端也能读。
  • 环境变量覆盖规则:用大写 NUXT_ 前缀 + 下划线分层级。runtimeConfig.public.apiBase 对应 NUXT_PUBLIC_API_BASE,runtimeConfig.apiSecret 对应 NUXT_API_SECRET。值会自动按类型转换(如 NUXT_PORT=3000 会变成数字 3000)。

⚠️ 一个高频坑:npm run dev / nuxt build 时 .env 会被读取,但运行已经构建好的服务端时 .env 不会被读取——生产环境要用真实环境变量(或进程管理器注入)覆盖 runtimeConfig。

6.7 自动导入(Auto-imports)是怎么工作的 ​

Nuxt 默认对以下内容做了自动导入,你无需手写 import:

  • composables/ 目录下的组合式函数。
  • components/ 目录下的组件(模板里直接用组件名)。
  • utils/ 目录下的工具函数。
  • Vue/Nuxt 的内置 API:ref、computed、useFetch、useState、defineNuxtConfig 等。

这是「约定优于配置」的体现:目录结构即导入规则。代价是「这个函数从哪来」变得不直观,所以:

  • 命名要克制、语义清晰,避免和全局 API 撞名。
  • 需要精确控制时,可以在 nuxt.config.ts 里用 imports 配置排除,或显式写 import(显式 import 同样有效)。

7. 页面、路由、布局 ​

7.1 页面是怎么变成路由的 ​

Nuxt 会根据 pages/ 目录自动生成路由。

这意味着:

  • 你通常不需要手写完整的 Vue Router 配置
  • 目录结构本身就是路由结构的一部分

7.2 动态路由 ​

text
pages/posts/[slug].vue

可匹配:

text
/posts/hello-nuxt

7.3 布局使用 ​

在页面中可以指定布局:

vue
<script setup lang="ts">
definePageMeta({
  layout: 'default',
})
</script>

7.4 页面元信息 ​

你也可以用 definePageMeta 配置:

  • 中间件
  • 页面动画
  • 布局
  • 自定义元数据

8. 数据获取:useFetch、useAsyncData、$fetch ​

这是 Nuxt 最容易学混的一部分。

8.1 useFetch ​

最常见、最适合页面首屏数据。

vue
<script setup lang="ts">
const { data, pending, error } = await useFetch('/api/posts')
</script>

适合:

  • 页面初始化数据
  • 希望结合 SSR / hydration 的场景

8.2 useAsyncData ​

更通用,更灵活。

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

适合:

  • 你想自定义数据获取逻辑
  • 需要更精细地控制 key、缓存、依赖关系

8.3 $fetch ​

这是更底层的请求能力。

适合:

  • 按钮点击后发请求
  • 非首屏、非 SSR 必须参与的交互请求

你可以这样记:

  • 页面首屏数据:优先 useFetch / useAsyncData
  • 用户点击行为:常用 $fetch

8.4 useFetch 的常用选项 ​

useFetch 背后其实是 useAsyncData + $fetch 的组合。常用选项:

ts
const { data, pending, error, refresh } = await useFetch('/api/posts', {
  key: 'posts',             // 手动指定缓存 key,跨组件共享同一份数据/状态
  server: true,             // 默认 true,是否在服务端也发起请求
  lazy: false,              // true 时不阻塞路由导航,先渲染再异步填充
  immediate: true,          // 是否立即请求
  watch: false,             // 是否监听响应式依赖自动重新请求
  pick: ['title'],          // 只把指定字段写入 payload,减小传给客户端的数据量
  transform: (res) => res.data,  // 对返回结果做一次处理
  dedupe: 'cancel',         // 同名 key 重复请求时的去重策略
})
  • lazy: true 和不加 await 效果接近:数据先为默认值,之后异步填充,导航不被阻塞。
  • key:两个组件用同一个 key,只会发一次请求,共享同一份 data/error。
  • dedupe:'cancel'(新请求取消旧请求)或 'defer'(旧的先返回,新的排队)。

8.5 三者的内部机制与 payload ​

理解下面这条链路,能少踩很多「数据明明有、页面却不对」的坑:

  1. 服务端渲染时,useFetch / useAsyncData 会把请求结果序列化进页面 payload(__NUXT_DATA__)。
  2. 浏览器拿到 HTML 后做 hydration,直接用 payload 里的数据填充 data,不会重复请求。
  3. 所以「服务端取到的数据」和「客户端首屏看到的数据」是一致的,这也是它们比裸 $fetch 更适合首屏的原因。

而 $fetch 是底层请求函数,它:

  • 不参与 SSR payload 序列化。
  • 在服务端调用时走 Nitro 内部通道,在客户端调用时走 HTTP。
  • 适合交互型、非首屏请求。

⚠️ 由此产生两个常见坑:

  • 在 useAsyncData 的回调里改外部 ref 等副作用,服务端也会执行一次,要意识到这段代码会跑两遍(服务端 + 客户端 hydration 各一次)。
  • 传给 useFetch 的 URL 或参数如果是响应式的,会被监听并自动重新请求;不想这样要设 watch: false。

9. 状态管理与组合式能力 ​

9.1 useState ​

Nuxt 提供了非常实用的状态封装方式:

typescript
const counter = useState('counter', () => 0)

这在 Nuxt 中很重要,因为它考虑了 SSR 场景下的状态一致性。

9.2 什么时候用 Pinia ​

如果状态开始变复杂,比如:

  • 用户体系
  • 权限体系
  • 购物车
  • 多模块协作

那就更适合引入 Pinia。

9.3 composables/ 的意义 ​

它让你把“逻辑”从页面里拆出来。

比如:

  • 一个 useAuth 管登录态
  • 一个 useApi 管请求封装
  • 一个 useSeo 管页面 SEO

这样项目会清晰很多。

9.4 useState 与 SSR 状态一致性(内部机制) ​

Nuxt 的 useState 不是简单包了一层 ref,它额外解决了 SSR 场景下的一个经典问题:状态要在服务端和客户端保持一致。

  • 服务端渲染时,useState 的初始值会被序列化进 payload。
  • 客户端 hydration 时,直接用 payload 里的值初始化,而不是重新执行初始化函数。
ts
// composables/useCounter.ts
export const useCounter = () => useState('counter', () => 0)

注意点:

  • 第一个参数 key 是全局唯一标识,跨组件共享同一份状态;key 冲突会导致状态串。
  • 初始化函数只在「服务端或客户端第一次访问且 payload 里没有该 key」时执行。
  • 如果初始化函数里有副作用(访问 window、随机数、时间戳),会导致服务端和客户端状态不一致,hydration 时出现警告或不匹配。

⚠️ 所以别把「只在浏览器才有的东西」(如 localStorage、window.innerWidth)直接塞进 useState 的初始化函数,这类逻辑要放到 onMounted 里再做。


10. 服务端能力与 Nitro ​

10.1 server/api ​

你可以直接写服务端接口:

typescript
export default defineEventHandler(() => {
  return {
    message: 'Hello from server API',
  }
})

这让前后端边界在小中型项目里更自然。

10.2 为什么这很重要 ​

很多初学者只把 Nuxt 当“Vue 的 SSR 工具”,但其实它更像:

“前端优先、但带服务端能力的全栈框架”

10.3 你要知道服务端和客户端不一样 ​

在服务端执行时:

  • 没有 window
  • 没有 document
  • 本地存储也不可直接访问

这会直接影响你的代码写法。

10.4 routeRules:按路由定制渲染策略(内部机制) ​

Nuxt 的强项之一,是能对「不同页面」指定「不同渲染策略」,而不是全站一刀切。这在第 4.4 节提到过,落地就是 nuxt.config.ts 里的 routeRules:

ts
export default defineNuxtConfig({
  routeRules: {
    '/': { prerender: true },       // 首页构建时预渲染成静态 HTML
    '/blog/**': { swr: 3600 },      // 博客按需渲染,缓存 1 小时(stale-while-revalidate)
    '/admin/**': { ssr: false },    // 后台纯客户端渲染
    '/api/**': { cors: true },      // 对 API 路由开启跨域
  },
})

常用规则:

规则含义
prerender构建时生成静态 HTML(SSG)
ssr是否服务端渲染(false 即 CSR)
swr按需渲染 + 缓存,适合数据变化不频繁的页面
redirect重定向
headers / cors自定义响应头 / 跨域

💡 这套能力由 Nitro 提供,意味着你可以把「营销页静态化、核心页 SSR、后台 CSR、接口带缓存」全部放进一个项目,而不用再额外架一层 Nginx 规则。


11. SEO、Meta 与首屏体验 ​

Nuxt 的一个优势就是内容类项目体验很好。

11.1 设置 Meta ​

vue
<script setup lang="ts">
useSeoMeta({
  title: '文章详情',
  description: '这是文章详情页',
})
</script>

11.2 为什么 Nuxt 对 SEO 更友好 ​

因为 SSR 或预渲染能让搜索引擎更容易拿到完整内容,而不是只拿到一个空壳 HTML。

11.3 首屏体验 ​

当页面在服务端就把结构和数据准备得更完整时:

  • 首屏更快可见
  • 感知性能更好

12. 插件、中间件、模块 ​

12.1 插件 ​

用于扩展应用能力,比如:

  • 注册全局方法
  • 接入第三方 SDK
  • 注入通用工具

12.2 中间件 ​

常见用途:

  • 登录校验
  • 权限控制
  • 页面跳转前处理

12.3 模块 ​

Nuxt 模块生态很丰富,比如:

  • 状态管理
  • UI 组件库集成
  • 图片优化
  • 站点地图
  • 分析埋点

初学者不要一上来装很多模块,先学框架本体。


13. TypeScript 在 Nuxt 中怎么用 ​

Nuxt 对 TypeScript 支持很好。

13.1 常见优势 ​

  • 页面和组件有更好的类型提示
  • useFetch / useAsyncData 能标注返回数据类型
  • 服务端接口也能得到类型约束

13.2 一个简单例子 ​

vue
<script setup lang="ts">
interface Post {
  id: number
  title: string
}

const { data } = await useFetch<Post[]>('/api/posts')
</script>

13.3 你要重点理解的不是“把所有地方都标类型” ​

而是:

  • 关键数据结构要清楚
  • 接口输入输出要稳定
  • 页面与服务端边界要明确

14. 部署、预渲染与上线思路 ​

14.1 常见部署目标 ​

Nuxt 可以部署到:

  • Node 服务器
  • Serverless 平台
  • Edge 环境
  • 静态托管(适合预渲染输出)

14.2 nuxt build ​

会生成可部署产物。

14.3 预渲染 ​

如果页面内容相对稳定,可以考虑预渲染,提高访问性能。

14.4 路由规则 ​

Nuxt 支持按页面粒度配置不同策略,这正是它相对普通 Vue SPA 很强的一点。


15. 进阶主题 ​

15.1 Layers ​

适合做多站点、多业务复用架构。

15.2 Modules ​

如果你想抽象出团队级能力,可以进一步研究 Nuxt 模块开发。

15.3 全栈项目边界设计 ​

随着项目变大,你会面临:

  • 前端页面与服务端接口如何拆分
  • 何时继续用 Nuxt 内置 API
  • 何时单独拆出后端服务

这些属于中高级阶段。


16. 初学者高频踩坑点 ​

16.1 把 Nuxt 当纯 Vue CLI 项目用 ​

Nuxt 有自己的目录约定和运行模型,不能只按普通 Vue SPA 思维写。

16.2 在 SSR 环境里直接用 window ​

这会报错。

16.3 首屏数据乱用 $fetch ​

页面初始化数据优先考虑 useFetch / useAsyncData。

16.4 全局状态直接乱用 ref ​

在 Nuxt 场景里,更应该先理解 useState 的 SSR 语义。

16.5 不理解客户端插件与服务端插件区别 ​

有些插件只能浏览器执行,要区分运行环境。


17. 推荐学习顺序 ​

建议按下面节奏学:

  1. 先看懂 Nuxt 是什么、能解决什么问题
  2. 再学目录结构、页面、路由、布局
  3. 再学 useFetch / useAsyncData / $fetch
  4. 再学 useState、plugins、middleware
  5. 再理解 SSR 与服务端执行环境
  6. 最后再碰部署、Layers、模块开发

如果你是 Vue 初学者,推荐顺序通常是:

  1. Vue 基础
  2. Vite
  3. TypeScript
  4. Nuxt

18. 学习资源 ​

以下链接我在 2026-06-15 做过核对。

官方文档 ​

视频资源 ​

学习建议 ​

  • 第一遍重点看 Introduction、Installation、Data Fetching
  • 第二遍开始结合自己的 Vue 项目理解 SSR 和服务端目录
  • 如果你还没学透 Vue,不要急着上 Nuxt 的高级特性

基于 VitePress 构建的个人学习文档知识库