轩辕李的博客 轩辕李的博客
首页
  • Java
  • Spring
  • 其他语言
  • 工具
  • HTML&CSS
  • JavaScript
  • 分布式
  • 代码质量管理
  • 基础
  • 操作系统
  • 计算机网络
  • 编程范式
  • 安全
  • 中间件
  • 心得
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

轩辕李

勇猛精进,星辰大海
首页
  • Java
  • Spring
  • 其他语言
  • 工具
  • HTML&CSS
  • JavaScript
  • 分布式
  • 代码质量管理
  • 基础
  • 操作系统
  • 计算机网络
  • 编程范式
  • 安全
  • 中间件
  • 心得
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • JavaScript

  • TypeScript

  • Node.js

  • Vue.js

    • Vue.js快速入门
    • Vue.js历代版本新特性
    • Nuxt.js极简入门
      • 一、从一个问题开始
        • 普通 Vue 项目的痛点
        • Nuxt 如何解决
      • 二、Nuxt.js 是什么
        • 简单理解
        • Nuxt 做了什么
        • 一个直观的对比
      • 三、创建第一个 Nuxt 项目
        • 1. 安装和创建
        • 2. 项目结构(只关注核心)
      • 四、理解服务端渲染(SSR)
        • 传统方式(客户端渲染)
        • Nuxt 方式(服务端渲染)
        • 实际例子
      • 五、核心功能(通过例子学习)
        • 1. 文件路由(最简单)
        • 2. 页面跳转
        • 3. 获取数据(核心)
        • 4. 自动导入组件
        • 5. 布局(Layouts)
        • 6. SEO 优化
      • 六、创建一个简单博客
        • 1. 创建首页
        • 2. 创建文章详情页
        • 3. 创建后端 API
        • 4. 添加布局
      • 七、常用功能
        • 1. 环境变量
        • 2. 状态管理(跨组件共享数据)
        • 3. 中间件(路由守卫)
        • 4. 加载状态
      • 八、部署上线
        • 1. 构建项目
        • 2. 部署到 Vercel(最简单)
        • 3. 部署到服务器
      • 九、常见问题
        • 1. 什么时候用 Nuxt?
        • 2. SSR vs SSG vs SPA
        • 3. 只在客户端运行的代码
        • 4. 数据获取的最佳实践
      • 十、学习路径
        • 1. 基础阶段(你现在在这里)
        • 2. 进阶阶段
        • 3. 高级阶段
        • 推荐资源
      • 十一、总结
        • Nuxt 的核心价值
        • 快速回顾
        • 下一步
  • 工程化

  • 浏览器与Web API

  • 前端
  • Vue.js
轩辕李
2025-07-11
目录

Nuxt.js极简入门

本文面向有 Vue.js 基础的开发者,通过通俗易懂的方式介绍 Nuxt.js 框架。我们会从一个简单的例子开始,逐步理解为什么需要 Nuxt、它解决了什么问题、以及如何使用它。

# 一、从一个问题开始

# 普通 Vue 项目的痛点

假设你用 Vue 3 开发了一个博客网站,遇到了这些问题:

<!-- 普通 Vue 项目 -->
<template>
  <div>
    <h1>{{ post.title }}</h1>
    <p>{{ post.content }}</p>
  </div>
</template>

<script setup>
import { ref, onMounted } from 'vue'

const post = ref(null)

// 问题1:数据在客户端获取
onMounted(async () => {
  const response = await fetch('/api/posts/1')
  post.value = await response.json()
})
</script>

你会遇到的问题:

  1. SEO 差:搜索引擎爬虫访问你的网站时,看到的是空白页面(因为数据要等 JavaScript 执行后才加载)
  2. 首屏慢:用户要等 JavaScript 下载→执行→获取数据→渲染,才能看到内容
  3. 路由麻烦:需要手动配置 Vue Router,写一堆路由代码
  4. 目录混乱:项目大了之后,不知道文件该放哪里

# Nuxt 如何解决

<!-- Nuxt 项目 -->
<template>
  <div>
    <h1>{{ post.title }}</h1>
    <p>{{ post.content }}</p>
  </div>
</template>

<script setup>
// Nuxt 在服务器端就把数据准备好了
const { data: post } = await useFetch('/api/posts/1')
</script>

Nuxt 的优势:

  1. ✅ SEO 好:服务器直接返回完整 HTML,搜索引擎能看到内容
  2. ✅ 首屏快:用户立即看到内容,无需等待 JavaScript
  3. ✅ 自动路由:创建 pages/about.vue 文件,自动生成 /about 路由
  4. ✅ 约定优于配置:清晰的目录结构,不用纠结文件放哪

# 二、Nuxt.js 是什么

# 简单理解

Nuxt.js = Vue.js + 服务端渲染 + 最佳实践

如果你熟悉 Vue.js,建议先阅读 Vue.js快速入门。

打个比方:

  • Vue.js:像是一套工具(锤子、螺丝刀、扳手)
  • Nuxt.js:像是整套装修方案(工具 + 施工流程 + 设计规范)

# Nuxt 做了什么

  1. 自动配置:帮你配置好 Vue Router、Vuex/Pinia、构建工具等
  2. 服务端渲染(SSR):在服务器上运行 Vue,生成 HTML 返回给浏览器
  3. 文件路由:根据文件结构自动生成路由,不用手写路由配置
  4. 自动导入:组件、函数自动导入,不用写 import
  5. 全栈能力:可以在同一个项目里写前端和后端 API

# 一个直观的对比

普通 Vue 项目:

// 需要手动配置路由
import { createRouter } from 'vue-router'
import Home from './pages/Home.vue'
import About from './pages/About.vue'

const router = createRouter({
  routes: [
    { path: '/', component: Home },
    { path: '/about', component: About }
  ]
})

Nuxt 项目:

只需要创建文件:
pages/
  index.vue    → 自动生成 / 路由
  about.vue    → 自动生成 /about 路由

# 三、创建第一个 Nuxt 项目

# 1. 安装和创建

# 创建项目(会问你一些问题,一路回车就行)
npx nuxi@latest init my-blog

# 进入项目
cd my-blog

# 安装依赖
npm install

# 启动开发服务器
npm run dev

打开浏览器访问 http://localhost:3000,你会看到 Nuxt 的欢迎页面。

# 2. 项目结构(只关注核心)

my-blog/
├── pages/           # 👈 页面文件(自动生成路由)
│   └── index.vue
├── components/      # 👈 组件(自动导入)
├── public/          # 👈 静态文件(如图片)
├── server/          # 👈 后端 API(可选)
│   └── api/
├── app.vue          # 👈 应用入口
└── nuxt.config.ts   # 👈 配置文件

初学者只需关注这几个目录:

  • pages/:放页面
  • components/:放组件
  • public/:放图片等静态文件

# 四、理解服务端渲染(SSR)

# 传统方式(客户端渲染)

1. 浏览器请求页面
   ↓
2. 服务器返回几乎空白的 HTML
   <div id="app"></div>
   ↓
3. 浏览器下载 Vue.js 和你的代码
   ↓
4. Vue 开始运行,获取数据
   ↓
5. 渲染页面
   ↓
6. 用户终于看到内容 😰(慢)

# Nuxt 方式(服务端渲染)

1. 浏览器请求页面
   ↓
2. 服务器运行 Vue,获取数据,生成完整 HTML
   ↓
3. 浏览器接收完整 HTML
   ↓
4. 用户立即看到内容 😊(快)
   ↓
5. Vue 接管页面,变成可交互的应用

# 实际例子

访问一个博客文章页面:

传统方式(CSR):

<!-- 浏览器收到的 HTML -->
<div id="app"></div>
<script src="app.js"></script>

<!-- 用户看到:空白 → 转圈 → 内容出现 -->

Nuxt 方式(SSR):

<!-- 浏览器收到的 HTML -->
<div id="app">
  <h1>为什么学习 Nuxt.js</h1>
  <p>Nuxt.js 是一个基于 Vue.js 的全栈框架...</p>
</div>
<script src="app.js"></script>

<!-- 用户看到:内容立即出现 ✨ -->

# 五、核心功能(通过例子学习)

# 1. 文件路由(最简单)

只需要创建文件,路由自动生成:

pages/
├── index.vue        → /
├── about.vue        → /about
├── blog/
│   ├── index.vue    → /blog
│   └── [id].vue     → /blog/123(动态路由)
└── user/
    └── [name].vue   → /user/alice

示例:创建关于页面

<!-- pages/about.vue -->
<template>
  <div>
    <h1>关于我们</h1>
    <p>这是关于页面</p>
  </div>
</template>

访问 http://localhost:3000/about,立即生效!

示例:动态路由

<!-- pages/blog/[id].vue -->
<template>
  <div>
    <h1>博客文章 {{ id }}</h1>
  </div>
</template>

<script setup>
const route = useRoute()
const id = route.params.id  // 获取 URL 中的 id
</script>

访问 http://localhost:3000/blog/123,id 就是 123。

# 2. 页面跳转

<template>
  <div>
    <!-- 使用 NuxtLink 组件跳转 -->
    <NuxtLink to="/">首页</NuxtLink>
    <NuxtLink to="/about">关于</NuxtLink>
    <NuxtLink to="/blog/123">文章123</NuxtLink>
  </div>
</template>

<script setup>
// 或者用代码跳转
const router = useRouter()

function goToAbout() {
  router.push('/about')
}
</script>

# 3. 获取数据(核心)

这是 Nuxt 最重要的功能之一。

错误示例(Vue 的方式,在 Nuxt 中不推荐):

<script setup>
import { ref, onMounted } from 'vue'

const posts = ref([])

// ❌ 不推荐:数据在客户端获取,SEO 不友好
onMounted(async () => {
  const response = await fetch('/api/posts')
  posts.value = await response.json()
})
</script>

正确示例(Nuxt 的方式):

<script setup>
// ✅ 推荐:数据在服务器端获取,SEO 友好
const { data: posts } = await useFetch('/api/posts')
</script>

<template>
  <div>
    <ul>
      <li v-for="post in posts" :key="post.id">
        {{ post.title }}
      </li>
    </ul>
  </div>
</template>

useFetch 的魔法:

  1. 在服务器上:发送真实的 HTTP 请求获取数据
  2. 在浏览器上:复用服务器获取的数据(不会重复请求)

# 4. 自动导入组件

创建组件后,不需要手动 import。

<!-- components/MyButton.vue -->
<template>
  <button class="my-button">
    <slot />
  </button>
</template>

<style scoped>
.my-button {
  background: blue;
  color: white;
  padding: 10px 20px;
}
</style>
<!-- pages/index.vue -->
<template>
  <div>
    <!-- 直接使用,无需 import! -->
    <MyButton>点击我</MyButton>
  </div>
</template>

# 5. 布局(Layouts)

想要多个页面共享相同的头部和底部?使用布局!

<!-- layouts/default.vue -->
<template>
  <div>
    <!-- 网站头部 -->
    <header>
      <nav>
        <NuxtLink to="/">首页</NuxtLink>
        <NuxtLink to="/about">关于</NuxtLink>
      </nav>
    </header>

    <!-- 页面内容显示在这里 -->
    <main>
      <slot />
    </main>

    <!-- 网站底部 -->
    <footer>
      <p>&copy; 2024 我的博客</p>
    </footer>
  </div>
</template>

所有页面自动使用这个布局!

# 6. SEO 优化

给每个页面设置标题和描述:

<!-- pages/about.vue -->
<script setup>
useHead({
  title: '关于我们',
  meta: [
    { name: 'description', content: '了解我们团队的故事' }
  ]
})
</script>

<template>
  <div>
    <h1>关于我们</h1>
  </div>
</template>

浏览器标签页会显示"关于我们",搜索引擎也能看到这些信息。

# 六、创建一个简单博客

让我们用 Nuxt 创建一个完整的小博客。

# 1. 创建首页

<!-- pages/index.vue -->
<script setup>
// 获取文章列表
const { data: posts } = await useFetch('/api/posts')
</script>

<template>
  <div class="home">
    <h1>我的博客</h1>
    
    <div class="posts">
      <div v-for="post in posts" :key="post.id" class="post-card">
        <h2>
          <NuxtLink :to="`/posts/${post.id}`">
            {{ post.title }}
          </NuxtLink>
        </h2>
        <p>{{ post.summary }}</p>
      </div>
    </div>
  </div>
</template>

<style scoped>
.home {
  max-width: 800px;
  margin: 0 auto;
  padding: 20px;
}

.post-card {
  margin-bottom: 30px;
  padding: 20px;
  border: 1px solid #ddd;
  border-radius: 8px;
}

.post-card h2 a {
  color: #42b983;
  text-decoration: none;
}
</style>

# 2. 创建文章详情页

<!-- pages/posts/[id].vue -->
<script setup>
const route = useRoute()
const id = route.params.id

// 获取文章详情
const { data: post } = await useFetch(`/api/posts/${id}`)

// 设置页面标题
useHead({
  title: post.value?.title || '文章详情'
})
</script>

<template>
  <div class="post-detail">
    <h1>{{ post.title }}</h1>
    <p class="date">发布于: {{ post.date }}</p>
    <div class="content">
      {{ post.content }}
    </div>
    
    <NuxtLink to="/" class="back-link">← 返回首页</NuxtLink>
  </div>
</template>

<style scoped>
.post-detail {
  max-width: 800px;
  margin: 0 auto;
  padding: 20px;
}

.date {
  color: #666;
  font-size: 14px;
}

.content {
  margin: 30px 0;
  line-height: 1.6;
}

.back-link {
  color: #42b983;
  text-decoration: none;
}
</style>

# 3. 创建后端 API

在同一个项目里写后端接口!

// server/api/posts.ts
export default defineEventHandler(() => {
  // 这里可以连接数据库,这里为了演示用假数据
  return [
    {
      id: 1,
      title: '学习 Nuxt.js',
      summary: 'Nuxt.js 让 Vue 开发更简单',
      content: 'Nuxt.js 是一个很棒的框架...',
      date: '2024-01-15'
    },
    {
      id: 2,
      title: '服务端渲染的好处',
      summary: 'SEO 和性能的双重提升',
      content: '服务端渲染可以...',
      date: '2024-01-16'
    }
  ]
})
// server/api/posts/[id].ts
export default defineEventHandler((event) => {
  const id = getRouterParam(event, 'id')
  
  // 模拟从数据库获取
  const posts = {
    '1': {
      id: 1,
      title: '学习 Nuxt.js',
      content: 'Nuxt.js 是一个基于 Vue.js 的全栈框架,它让服务端渲染变得简单...',
      date: '2024-01-15'
    },
    '2': {
      id: 2,
      title: '服务端渲染的好处',
      content: '服务端渲染可以提升 SEO,加快首屏加载...',
      date: '2024-01-16'
    }
  }
  
  return posts[id]
})

# 4. 添加布局

<!-- layouts/default.vue -->
<template>
  <div class="layout">
    <header class="header">
      <nav>
        <NuxtLink to="/" class="logo">我的博客</NuxtLink>
        <div class="nav-links">
          <NuxtLink to="/">首页</NuxtLink>
          <NuxtLink to="/about">关于</NuxtLink>
        </div>
      </nav>
    </header>

    <main class="main">
      <slot />
    </main>

    <footer class="footer">
      <p>&copy; 2024 我的博客. Powered by Nuxt.js</p>
    </footer>
  </div>
</template>

<style scoped>
.layout {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
}

.header {
  background: #42b983;
  color: white;
  padding: 1rem 2rem;
}

.header nav {
  max-width: 1200px;
  margin: 0 auto;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.logo {
  font-size: 1.5rem;
  font-weight: bold;
  color: white;
  text-decoration: none;
}

.nav-links a {
  margin-left: 2rem;
  color: white;
  text-decoration: none;
}

.main {
  flex: 1;
  padding: 2rem;
}

.footer {
  background: #f5f5f5;
  padding: 2rem;
  text-align: center;
  color: #666;
}
</style>

现在运行 npm run dev,你就有了一个完整的博客!

# 七、常用功能

# 1. 环境变量

# .env
NUXT_PUBLIC_API_BASE=https://api.example.com
<script setup>
const config = useRuntimeConfig()
const apiBase = config.public.apiBase
</script>

# 2. 状态管理(跨组件共享数据)

// composables/useUser.ts
export const useUser = () => {
  // 创建全局共享的状态
  const user = useState('user', () => ({
    name: '',
    email: ''
  }))
  
  const login = (name: string, email: string) => {
    user.value = { name, email }
  }
  
  const logout = () => {
    user.value = { name: '', email: '' }
  }
  
  return {
    user,
    login,
    logout
  }
}
<!-- 任何组件中使用 -->
<script setup>
const { user, login } = useUser()
</script>

<template>
  <div v-if="user.name">
    欢迎, {{ user.name }}
  </div>
</template>

# 3. 中间件(路由守卫)

// middleware/auth.ts
export default defineNuxtRouteMiddleware((to, from) => {
  const { user } = useUser()
  
  // 如果用户未登录,跳转到登录页
  if (!user.value.name) {
    return navigateTo('/login')
  }
})
<!-- pages/admin.vue -->
<script setup>
// 使用中间件保护这个页面
definePageMeta({
  middleware: 'auth'
})
</script>

<template>
  <div>
    <h1>管理后台</h1>
  </div>
</template>

# 4. 加载状态

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

<template>
  <div>
    <!-- 加载中 -->
    <div v-if="pending">加载中...</div>
    
    <!-- 错误 -->
    <div v-else-if="error">出错了: {{ error.message }}</div>
    
    <!-- 数据 -->
    <div v-else>
      <div v-for="post in posts" :key="post.id">
        {{ post.title }}
      </div>
    </div>
  </div>
</template>

# 八、部署上线

# 1. 构建项目

# 生成生产版本
npm run build

# 预览生产版本
npm run preview

# 2. 部署到 Vercel(最简单)

  1. 把代码推送到 GitHub
  2. 访问 vercel.com (opens new window)
  3. 导入你的 GitHub 仓库
  4. 点击部署,完成!

Vercel 会自动识别 Nuxt 项目并正确部署。

# 3. 部署到服务器

# 构建
npm run build

# 上传 .output 文件夹到服务器

# 在服务器上运行
node .output/server/index.mjs

# 九、常见问题

# 1. 什么时候用 Nuxt?

适合用 Nuxt:

  • ✅ 需要 SEO(博客、电商、新闻网站)
  • ✅ 需要快速首屏加载
  • ✅ 想要约定式的项目结构
  • ✅ 需要全栈能力(前端 + API)

不适合用 Nuxt:

  • ❌ 纯后台管理系统(不需要 SEO)
  • ❌ 对服务器资源有严格限制
  • ❌ 只需要简单的静态网站

# 2. SSR vs SSG vs SPA

// nuxt.config.ts
export default defineNuxtConfig({
  // SSR: 每次请求都在服务器渲染(默认)
  ssr: true,
  
  // SSG: 构建时生成静态 HTML
  // 适合博客、文档站
  
  // SPA: 关闭 SSR,变成普通 Vue 应用
  ssr: false
})

# 3. 只在客户端运行的代码

有些代码只能在浏览器运行(如操作 window):

<script setup>
onMounted(() => {
  // ✅ onMounted 只在客户端执行
  console.log(window.innerWidth)
})
</script>

<template>
  <!-- ✅ ClientOnly 组件包裹的内容只在客户端渲染 -->
  <ClientOnly>
    <MapComponent />
  </ClientOnly>
</template>

# 4. 数据获取的最佳实践

<script setup>
// ✅ 推荐:使用 useFetch
const { data } = await useFetch('/api/posts')

// ❌ 不推荐:在 onMounted 中获取
onMounted(async () => {
  const response = await fetch('/api/posts')
  // ...
})

// ✅ 推荐:带参数的请求
const page = ref(1)
const { data } = await useFetch('/api/posts', {
  query: { page }  // page 变化时自动重新请求
})
</script>

# 十、学习路径

# 1. 基础阶段(你现在在这里)

  • ✅ 理解为什么需要 Nuxt
  • ✅ 掌握文件路由
  • ✅ 学会用 useFetch 获取数据
  • ✅ 完成一个简单项目

# 2. 进阶阶段

  • 学习状态管理(Pinia)
  • 理解服务端渲染原理
  • 掌握中间件和插件
  • 学习性能优化

# 3. 高级阶段

  • 自定义服务器
  • 深入理解 Nitro 引擎
  • 模块开发
  • 复杂的部署场景

# 推荐资源

  • Nuxt 3 官方文档 (opens new window):非常详细易懂
  • Nuxt 3 中文文档 (opens new window)
  • Vue.js快速入门:补充 Vue 基础
  • Vite极简入门:了解构建工具

# 十一、总结

# Nuxt 的核心价值

  1. 简化开发:自动路由、自动导入,专注业务逻辑
  2. 性能优化:服务端渲染,首屏秒开
  3. SEO 友好:搜索引擎能看到完整内容
  4. 全栈能力:一个项目搞定前后端

# 快速回顾

创建项目     npx nuxi init my-app
启动开发     npm run dev
创建页面     pages/about.vue → /about 路由
获取数据     await useFetch('/api/data')
页面跳转     <NuxtLink to="/about">
SEO 优化     useHead({ title: '标题' })
后端 API     server/api/hello.ts

# 下一步

  1. 动手实践:创建一个真实项目(博客、作品集、商城)
  2. 阅读文档:Nuxt 官方文档写得很好,值得细读
  3. 学习 Vue:如果 Vue 基础不够扎实,先补充 Vue 知识
  4. 关注社区:查看优秀的开源 Nuxt 项目

记住:Nuxt 不是魔法,它只是让 Vue 开发更简单。先理解 Vue,再用 Nuxt,就会发现一切都很自然。

祝你变得更强!

编辑 (opens new window)
#Nuxt.js#SSR#全栈框架#Vue.js
上次更新: 2025/11/12
Vue.js历代版本新特性
Vite极简入门

← Vue.js历代版本新特性 Vite极简入门→

最近更新
01
AI编程时代的一些心得
09-11
02
Claude Code与Codex的协同工作
09-01
03
Claude Code 最佳实践(个人版)
08-01
更多文章>
Theme by Vdoing | Copyright © 2018-2025 京ICP备2021021832号-2 | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式