Nuxt.js 中文教程

1. 什么是 Nuxt.js?

Nuxt.js 是一个基于 Vue.js 的开源前端框架,专注于构建服务器端渲染 (SSR) 和静态站点生成 (SSG) 的应用。它由 Alexandre Chopin 和 Sébastien Chopin 创建,旨在简化 Vue 应用的开发流程,提供更好的性能和 SEO 友好性。

1.1 Nuxt.js 的核心优势

  • **服务器端渲染 (SSR)**:提高首屏加载速度和 SEO 友好性。
  • **静态站点生成 (SSG)**:预渲染页面,提供极致的加载性能。
  • 自动代码拆分:减小初始加载体积,提高页面加载速度。
  • 内置路由:基于文件系统的路由,无需额外配置。
  • API 路由:在同一代码库中构建 API 接口。
  • 开发体验:热模块替换、快速刷新等功能。
  • 模块系统:通过模块扩展核心功能,如 PWA、国际化等。
  • 部署便捷:支持多种部署方式,包括静态托管、Node.js 服务器等。

2. 安装和初始化

2.1 使用 nuxi 初始化项目

Nuxt.js 3+ 使用 nuxi 命令行工具来初始化项目:

# 使用 npm
npx nuxi@latest init my-nuxt-app

# 使用 yarn
yarn create nuxt-app@latest my-nuxt-app

# 使用 pnpm
pnpm create nuxt-app@latest my-nuxt-app

2.2 选择模板

nuxi 会提示你选择项目配置:

  • Project name:项目名称
  • Package manager:包管理器(npm、yarn、pnpm)
  • UI framework:UI 框架(None、Tailwind CSS、Bootstrap 等)
  • TypeScript:是否使用 TypeScript
  • Nuxt modules:是否集成 Nuxt 模块(如 Content、Image 等)
  • Linting tools:代码检查工具(ESLint、Prettier 等)
  • Testing framework:测试框架(Vitest、Jest 等)
  • Rendering mode:渲染模式(SSR、SSG、SPA)
  • Deployment target:部署目标(Server、Static)

2.3 手动安装

如果你想手动安装 Nuxt.js,可以按照以下步骤:

# 创建项目目录
mkdir my-nuxt-app
cd my-nuxt-app

# 初始化 package.json
npm init -y

# 安装依赖
npm install nuxt vue vue-router

# 添加脚本
# 在 package.json 中添加:
# "scripts": {
#   "dev": "nuxt dev",
#   "build": "nuxt build",
#   "generate": "nuxt generate",
#   "preview": "nuxt preview"
# }

2.4 验证安装

# 启动开发服务器
npm run dev

# 访问 http://localhost:3000

3. 基本目录结构

Nuxt.js 3+ 项目的默认目录结构如下:

my-nuxt-app/
├── app/             # 应用目录
│   ├── components/  # 组件目录
│   ├── composables/ # 组合式函数目录
│   ├── pages/       # 页面路由目录
│   ├── plugins/     # 插件目录
│   └── utils/       # 工具函数目录
├── assets/          # 静态资源目录(会被 webpack 处理)
├── public/          # 静态资源目录(直接复制到输出目录)
├── server/          # 服务器端目录
│   ├── api/         # API 路由
│   └── middleware/  # 服务器端中间件
├── nuxt.config.ts   # Nuxt.js 配置文件
├── package.json     # 项目配置文件
└── README.md        # 项目说明文件

4. 核心功能

4.1 路由系统

Nuxt.js 使用基于文件系统的路由,文件路径即为路由路径:

  • app/pages/index.vue/
  • app/pages/about.vue/about
  • app/pages/blog/[id].vue/blog/123(动态路由)
  • app/pages/blog/[...slug].vue/blog/2023/01/01(捕获所有路由)

动态路由示例:

<!-- app/pages/blog/[id].vue -->
<template>
  <div>
    <h1>Blog Post: {{ id }}</h1>
  </div>
</template>

<script setup>
const route = useRoute();
const { id } = route.params;
</script>

4.2 数据获取

Nuxt.js 提供了多种数据获取方式,根据渲染策略选择合适的方法:

4.2.1 静态生成(SSG)

使用 useAsyncDatauseFetch 组合进行数据获取:

<!-- app/pages/blog.vue -->
<template>
  <div>
    <h1>Blog</h1>
    <ul>
      <li v-for="post in posts" :key="post.id">
        <NuxtLink :to="`/blog/${post.id}`">{{ post.title }}</NuxtLink>
      </li>
    </ul>
  </div>
</template>

<script setup>
const { data: posts } = await useAsyncData('posts', async () => {
  const res = await fetch('https://api.example.com/posts');
  return res.json();
});
</script>

4.2.2 服务器端渲染(SSR)

对于需要每次请求都获取最新数据的页面,使用 useAsyncData 即可:

<!-- app/pages/user/[id].vue -->
<template>
  <div>
    <h1>User: {{ user.name }}</h1>
  </div>
</template>

<script setup>
const route = useRoute();
const { id } = route.params;

const { data: user } = await useAsyncData(`user-${id}`, async () => {
  const res = await fetch(`https://api.example.com/users/${id}`);
  return res.json();
});
</script>

4.2.3 客户端数据获取

对于不需要 SEO 的数据,可以在客户端获取:

<!-- app/pages/dashboard.vue -->
<template>
  <div>
    <h1>Dashboard</h1>
    <div v-if="loading">Loading...</div>
    <div v-else>
      <!-- 显示数据 -->
    </div>
  </div>
</template>

<script setup>
const { ref, onMounted } = Vue;
const data = ref([]);
const loading = ref(true);

onMounted(async () => {
  const res = await fetch('/api/dashboard');
  data.value = await res.json();
  loading.value = false;
});
</script>

4.3 API 路由

Nuxt.js 允许你在 server/api 目录中创建 API 接口:

// server/api/hello.js
export default defineEventHandler((event) => {
  return {
    name: 'John Doe'
  };
});

使用方法:

# 访问 API 接口
curl http://localhost:3000/api/hello

4.4 样式解决方案

Nuxt.js 支持多种样式解决方案:

4.4.1 CSS 模块

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

<style scoped>
.button {
  padding: 10px 20px;
  background-color: #0070f3;
  color: white;
  border: none;
  border-radius: 4px;
}
</style>

4.4.2 Tailwind CSS

Nuxt.js 3+ 提供了内置的 Tailwind CSS 支持:

# 安装 Tailwind CSS
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p

配置示例:

// tailwind.config.js
/** @type {import('tailwindcss').Config} */
export default {
  content: [
    "./app/**/*.{vue,js,ts,jsx,tsx}",
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}

// app.css
@tailwind base;
@tailwind components;
@tailwind utilities;

使用方法:

<!-- app/pages/index.vue -->
<template>
  <div class="flex flex-col items-center justify-center min-h-screen">
    <h1 class="text-4xl font-bold">Hello Nuxt.js</h1>
    <p class="text-gray-600 mt-4">Welcome to Nuxt.js with Tailwind CSS</p>
  </div>
</template>

4.4.3 全局样式

/* app/assets/css/globals.css */
* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

body {
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}

配置示例:

// nuxt.config.ts
export default defineNuxtConfig({
  css: ['~/assets/css/globals.css']
});

5. 高级特性

5.1 中间件

Nuxt.js 中间件允许你在路由导航前后运行代码:

5.1.1 页面中间件

// middleware/auth.js
export default defineNuxtRouteMiddleware((to, from) => {
  // 检查是否有认证令牌
  const token = useCookie('auth-token');

  // 如果没有令牌,重定向到登录页
  if (!token.value) {
    return navigateTo('/login');
  }
});

使用方法:

<!-- app/pages/dashboard.vue -->
<template>
  <div>
    <h1>Dashboard</h1>
  </div>
</template>

<script setup>
// 在页面中使用中间件
definePageMeta({
  middleware: ['auth']
});
</script>

5.1.2 服务器中间件

// server/middleware/logger.js
export default defineEventHandler((event) => {
  console.log('Request:', event.node.req.url);
});

5.2 增量静态再生

Nuxt.js 3+ 支持增量静态再生(ISR),允许你在构建后更新静态页面:

<!-- app/pages/blog/[id].vue -->
<template>
  <div>
    <h1>{{ post.title }}</h1>
    <div>{{ post.content }}</div>
  </div>
</template>

<script setup>
const route = useRoute();
const { id } = route.params;

const { data: post } = await useAsyncData(`post-${id}`, async () => {
  const res = await fetch(`https://api.example.com/posts/${id}`);
  return res.json();
}, {
  // 增量静态再生,每 60 秒重新生成
  revalidate: 60
});
</script>

<script>
export default {
  // 生成静态路径
generate: {
    routes: async () => {
      const res = await fetch('https://api.example.com/posts');
      const posts = await res.json();
      return posts.map(post => `/blog/${post.id}`);
    }
  }
};
</script>

5.3 图像优化

Nuxt.js 提供了内置的图像优化功能:

<!-- components/OptimizedImage.vue -->
<template>
  <div>
    <h2>优化后的图像</h2>
    <NuxtImg
      src="/nuxt.svg"
      alt="Nuxt Logo"
      width="120"
      height="40"
    />
  </div>
</template>

5.4 国际化

Nuxt.js 支持国际化路由和内容:

安装国际化模块:

npm install @nuxtjs/i18n

配置示例:

// nuxt.config.ts
export default defineNuxtConfig({
  modules: ['@nuxtjs/i18n'],
  i18n: {
    locales: [
      { code: 'en', iso: 'en-US', name: 'English' },
      { code: 'zh', iso: 'zh-CN', name: '中文' }
    ],
    defaultLocale: 'en',
    vueI18n: {
      messages: {
        en: {
          welcome: 'Welcome'
        },
        zh: {
          welcome: '欢迎'
        }
      }
    }
  }
});

使用方法:

<!-- app/pages/index.vue -->
<template>
  <div>
    <h1>{{ $t('welcome') }}</h1>
    <NuxtLink to="/">English</NuxtLink>
    <NuxtLink to="/zh">中文</NuxtLink>
  </div>
</template>

6. 模块系统

Nuxt.js 的模块系统允许你扩展核心功能,以下是一些常用的模块:

6.1 @nuxt/content

用于管理内容,支持 Markdown、YAML 等格式:

npm install @nuxt/content

配置示例:

// nuxt.config.ts
export default defineNuxtConfig({
  modules: ['@nuxt/content']
});

使用方法:

<!-- app/pages/blog.vue -->
<template>
  <div>
    <h1>Blog</h1>
    <ul>
      <li v-for="article in articles" :key="article._path">
        <NuxtLink :to="article._path">{{ article.title }}</NuxtLink>
      </li>
    </ul>
  </div>
</template>

<script setup>
const { data: articles } = await useAsyncData('articles', async () => {
  const { $content } = useNuxtApp();
  return $content('blog').find();
});
</script>

6.2 @nuxt/image

用于优化图像加载:

npm install @nuxt/image

配置示例:

// nuxt.config.ts
export default defineNuxtConfig({
  modules: ['@nuxt/image']
});

6.3 @nuxtjs/pwa

用于创建渐进式 Web 应用:

npm install @nuxtjs/pwa

配置示例:

// nuxt.config.ts
export default defineNuxtConfig({
  modules: ['@nuxtjs/pwa'],
  pwa: {
    manifest: {
      name: 'My Nuxt App',
      short_name: 'Nuxt App',
description: 'A Nuxt.js application',
      theme_color: '#0070f3'
    }
  }
});

7. 最佳实践

7.1 性能优化

  • 使用静态生成:对于内容不经常变化的页面,使用 SSG 提高性能。
  • 增量静态再生:对于频繁变化的内容,使用 ISR 平衡性能和新鲜度。
  • 代码拆分:使用动态导入减少初始加载体积。
  • 图像优化:使用 NuxtImg 组件优化图像加载。
  • 缓存策略:合理设置缓存头,减少重复请求。

7.2 目录结构

my-nuxt-app/
├── app/             # 应用目录
│   ├── components/  # 可复用组件
│   ├── composables/ # 组合式函数
│   ├── pages/       # 页面路由
│   ├── plugins/     # 插件
│   └── utils/       # 工具函数
├── assets/          # 静态资源(会被 webpack 处理)
├── public/          # 静态资源(直接复制)
├── server/          # 服务器端代码
│   ├── api/         # API 路由
│   └── middleware/  # 服务器中间件
├── content/         # 内容文件(使用 @nuxt/content 时)
├── nuxt.config.ts   # Nuxt.js 配置
└── package.json     # 项目配置

7.3 部署策略

7.3.1 静态部署

对于静态站点,可以使用 nuxt generate 生成静态文件:

# 生成静态文件
npm run generate

# 部署到静态托管服务
# 如 Netlify、Vercel、GitHub Pages 等

7.3.2 Node.js 服务器部署

对于需要服务器端渲染的应用,可以使用 nuxt build 构建并部署到 Node.js 服务器:

# 构建应用
npm run build

# 启动服务器
npm run start

# 部署到 Node.js 服务器
# 如 Heroku、AWS EC2、DigitalOcean 等

7.3.3 容器化部署

使用 Docker 容器化部署:

# Dockerfile
FROM node:18-alpine

WORKDIR /app

COPY package*.json ./
RUN npm install

COPY . .
RUN npm run build

EXPOSE 3000

CMD ["npm", "run", "start"]

7.4 安全最佳实践

  • 环境变量:使用 .env 文件存储敏感信息
  • API 路由保护:验证 API 请求的身份认证
  • 输入验证:验证用户输入,防止 XSS 和 SQL 注入
  • CORS 配置:合理配置 CORS 策略
  • 依赖管理:定期更新依赖,修复安全漏洞

8. 常见问题与解决方案

8.1 路由问题

问题:动态路由参数获取不到

解决方案

  • 使用 useRoute() 钩子获取路由参数
  • 确保文件名格式正确,如 [id].vue
  • 检查路由配置是否正确

8.2 数据获取问题

问题:useAsyncData 不更新数据

解决方案

  • 添加 revalidate 属性启用增量静态再生
  • 检查数据获取逻辑是否正确
  • 确保 API 接口返回最新数据

8.3 样式问题

问题:CSS 模块不生效

解决方案

  • 确保使用 scoped 属性
  • 正确导入和使用样式
  • 检查 CSS 选择器是否正确

8.4 部署问题

问题:静态部署后页面空白

解决方案

  • 检查路由配置是否正确
  • 确保使用了正确的构建命令
  • 检查部署环境的配置

8.5 性能问题

问题:页面加载缓慢

解决方案

  • 使用静态生成或增量静态再生
  • 优化图像和资源
  • 减少初始加载体积
  • 使用代码拆分

9. 总结

Nuxt.js 是一个功能强大的 Vue 框架,它提供了服务器端渲染、静态站点生成、路由、API 路由等核心功能,使开发者能够构建现代化、高性能的 Web 应用。

通过本教程,你应该已经了解了 Nuxt.js 的基本概念、核心功能和最佳实践。Nuxt.js 不断发展,新的特性和改进不断推出,建议你关注官方文档和更新日志,保持对最新功能的了解。

Nuxt.js 的优势在于它提供了一套完整的解决方案,从开发到部署的全流程支持,使开发者能够专注于业务逻辑的实现,而不是基础设施的搭建。无论是构建个人网站、企业应用还是电商平台,Nuxt.js 都能满足你的需求。

« 上一篇 Next.js 中文教程 下一篇 » Gatsby 中文教程