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-app2.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:30003. 基本目录结构
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→/aboutapp/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)
使用 useAsyncData 和 useFetch 组合进行数据获取:
<!-- 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/hello4.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 都能满足你的需求。