Nuxt.js 指南
目录
简介
Nuxt.js 是一个基于 Vue.js 的开源框架,它使得创建通用应用变得简单。它预设了利用 Vue.js 开发服务端渲染应用所需要的各种配置,同时也可以生成静态站点。
Nuxt.js 的主要特性
- 自动路由配置
- 服务端渲染 (SSR)
- 静态站点生成 (SSG)
- 代码分割
- 中间件支持
- 布局系统
- 数据获取
- 状态管理
- SEO 优化
环境准备
系统要求
- Node.js 12.x 或更高版本
- npm 或 yarn 包管理器
安装 Nuxt.js
# 使用 npx
npx create-nuxt-app my-project
# 或使用 yarn
yarn create nuxt-app my-project
安装过程中的选项
- 项目名称
- 包管理器 (npm/yarn/pnpm)
- UI 框架 (Bootstrap, Tailwind, Vuetify 等)
- Nuxt.js 模块 (Axios, PWA 等)
- 代码规范工具 (ESLint, Prettier 等)
- 测试框架 (Jest, AVA 等)
- 渲染模式 (Universal/SSR, SPA, Static)
- 部署目标 (Server, Static)
- 开发工具 (jsconfig.json)
- Git 初始化
项目创建
基本项目结构
my-project/
├── assets/ # 未编译的静态资源
├── components/ # Vue 组件
├── layouts/ # 布局组件
├── middleware/ # 中间件
├── pages/ # 页面组件
├── plugins/ # 插件
├── static/ # 静态文件
├── store/ # Vuex 存储
├── nuxt.config.js # Nuxt.js 配置
└── package.json # 项目依赖
启动开发服务器
# 开发模式
npm run dev
# 构建生产版本
npm run build
# 启动生产服务器
npm run start
# 生成静态项目
npm run generate
项目结构
1. pages 目录
pages 目录中的文件会自动生成路由配置。
<!-- pages/index.vue -->
<template>
<div>
<h1>首页</h1>
</div>
</template>
<script>
export default {
name: 'HomePage'
}
</script>
2. components 目录
组件可以全局注册,无需导入即可使用。
<!-- components/Button.vue -->
<template>
<button class="btn" @click="$emit('click')">
<slot></slot>
</button>
</template>
<script>
export default {
name: 'Button'
}
</script>
3. layouts 目录
布局文件用于定义页面模板。
<!-- layouts/default.vue -->
<template>
<div>
<header>
<nav>
<NuxtLink to="/">首页</NuxtLink>
<NuxtLink to="/about">关于</NuxtLink>
</nav>
</header>
<main>
<Nuxt />
</main>
<footer>
<p>© 2023 My Nuxt App</p>
</footer>
</div>
</template>
4. assets 目录
存放需要编译的资源文件。
/* assets/scss/main.scss */
$primary-color: #42b983;
.btn {
background-color: $primary-color;
color: white;
padding: 10px 20px;
border-radius: 4px;
}
5. static 目录
存放不需要编译的静态文件。
static/
├── favicon.ico
├── robots.txt
└── images/
└── logo.png
路由系统
1. 基本路由
pages 目录结构自动生成路由:
pages/
├── index.vue # /
├── about.vue # /about
├── users/
│ ├── index.vue # /users
│ └── _id.vue # /users/:id
└── _slug.vue # /:slug
2. 动态路由
使用下划线前缀创建动态路由:
<!-- pages/users/_id.vue -->
<template>
<div>
<h1>用户详情</h1>
<p>用户 ID: {{ $route.params.id }}</p>
</div>
</template>
<script>
export default {
validate({ params }) {
return /^\d+$/.test(params.id)
}
}
</script>
3. 嵌套路由
使用目录结构创建嵌套路由:
pages/
└── parent/
├── index.vue # /parent
└── child.vue # /parent/child
4. 路由中间件
在页面组件中使用中间件:
<!-- pages/admin/index.vue -->
<template>
<div>
<h1>管理面板</h1>
</div>
</template>
<script>
export default {
middleware: 'auth'
}
</script>
数据获取
1. asyncData 方法
在页面组件渲染前获取数据:
<!-- pages/posts/index.vue -->
<template>
<div>
<h1>文章列表</h1>
<ul>
<li v-for="post in posts" :key="post.id">
{{ post.title }}
</li>
</ul>
</div>
</template>
<script>
export default {
async asyncData({ $axios }) {
const posts = await $axios.$get('https://api.example.com/posts')
return { posts }
}
}
</script>
2. fetch 方法
在 store 中获取数据:
<!-- pages/posts/index.vue -->
<template>
<div>
<h1>文章列表</h1>
<ul>
<li v-for="post in posts" :key="post.id">
{{ post.title }}
</li>
</ul>
</div>
</template>
<script>
import { mapState } from 'vuex'
export default {
computed: {
...mapState(['posts'])
},
fetch({ store }) {
return store.dispatch('posts/fetchPosts')
}
}
</script>
3. 使用 Axios 模块
配置 Axios 模块:
// nuxt.config.js
export default {
modules: [
'@nuxtjs/axios'
],
axios: {
baseURL: 'https://api.example.com'
}
}
状态管理
1. Vuex 存储
创建 Vuex 模块:
// store/posts.js
export const state = () => ({
posts: []
})
export const mutations = {
SET_POSTS(state, posts) {
state.posts = posts
}
}
export const actions = {
async fetchPosts({ commit }) {
const posts = await this.$axios.$get('/posts')
commit('SET_POSTS', posts)
}
}
2. 使用存储
在组件中使用 Vuex:
<template>
<div>
<h1>文章列表</h1>
<ul>
<li v-for="post in posts" :key="post.id">
{{ post.title }}
</li>
</ul>
</div>
</template>
<script>
import { mapState, mapActions } from 'vuex'
export default {
computed: {
...mapState('posts', ['posts'])
},
methods: {
...mapActions('posts', ['fetchPosts'])
},
mounted() {
this.fetchPosts()
}
}
</script>
中间件
1. 命名中间件
创建中间件文件:
// middleware/auth.js
export default function ({ store, redirect }) {
if (!store.state.authenticated) {
return redirect('/login')
}
}
2. 匿名中间件
在页面组件中定义:
<script>
export default {
middleware({ store, redirect }) {
if (!store.state.authenticated) {
return redirect('/login')
}
}
}
</script>
3. 全局中间件
在 nuxt.config.js 中配置:
// nuxt.config.js
export default {
router: {
middleware: ['stats']
}
}
插件系统
1. 创建插件
// plugins/vue-notifications.js
import Vue from 'vue'
import VueNotifications from 'vue-notifications'
Vue.use(VueNotifications)
2. 注册插件
在 nuxt.config.js 中配置:
// nuxt.config.js
export default {
plugins: [
'~/plugins/vue-notifications'
]
}
3. 客户端/服务端插件
// nuxt.config.js
export default {
plugins: [
{ src: '~/plugins/vue-notifications', mode: 'client' }
]
}
布局系统
1. 默认布局
<!-- layouts/default.vue -->
<template>
<div>
<header>
<nav>
<NuxtLink to="/">首页</NuxtLink>
<NuxtLink to="/about">关于</NuxtLink>
</nav>
</header>
<main>
<Nuxt />
</main>
<footer>
<p>© 2023 My Nuxt App</p>
</footer>
</div>
</template>
2. 自定义布局
<!-- layouts/blog.vue -->
<template>
<div class="blog-layout">
<header class="blog-header">
<h1>我的博客</h1>
</header>
<main class="blog-content">
<Nuxt />
</main>
<aside class="blog-sidebar">
<div class="widget">
<h3>最新文章</h3>
<!-- 侧边栏内容 -->
</div>
</aside>
</div>
</template>
3. 使用布局
在页面组件中指定布局:
<!-- pages/about.vue -->
<template>
<div>
<h1>关于我们</h1>
</div>
</template>
<script>
export default {
layout: 'blog'
}
</script>
部署
1. 服务端渲染 (SSR)
# 构建应用
npm run build
# 启动服务
npm run start
2. 静态站点生成 (SSG)
# 生成静态文件
npm run generate
3. 单页应用 (SPA)
在 nuxt.config.js 中配置:
// nuxt.config.js
export default {
mode: 'spa'
}
4. 部署到 Vercel
- 安装 Vercel CLI
npm i -g vercel
- 部署项目
vercel
5. 部署到 Netlify
- 创建 netlify.toml 文件
[build]
command = "npm run generate"
publish = "dist"
[[redirects]]
from = "/*"
to = "/index.html"
status = 200
- 连接 GitHub 仓库并部署
最佳实践
1. 性能优化
- 使用
nuxt-image
优化图片 - 启用组件懒加载
- 使用
keep-alive
缓存组件 - 优化 CSS 和 JavaScript 打包
2. SEO 优化
- 使用
head()
方法设置元数据 - 实现动态 sitemap
- 添加结构化数据
- 优化页面加载速度
3. 代码组织
- 使用模块化结构
- 遵循 Vue.js 风格指南
- 实现组件复用
- 使用 TypeScript 增加类型安全
4. 测试
- 单元测试 (Jest)
- 组件测试 (Vue Test Utils)
- E2E 测试 (Cypress)
- 性能测试 (Lighthouse)
5. 安全
- 防止 XSS 攻击
- 实现 CSRF 保护
- 使用 HTTPS
- 安全存储敏感数据
常见问题解决
1. 路由问题
- 检查 pages 目录结构
- 使用
router.push()
进行编程式导航 - 处理动态路由参数
2. 数据获取问题
- 使用
asyncData
或fetch
方法 - 处理加载状态和错误
- 实现数据缓存
3. 样式问题
- 使用 CSS 模块
- 配置 PostCSS
- 处理全局样式
4. 构建问题
- 优化构建配置
- 处理依赖冲突
- 解决内存不足问题