Nuxt2
以下是 Nuxt 2(基于 Vue 2 + Webpack)的核心重点知识梳理,覆盖基础认知、核心功能、关键概念及最佳实践:
一、Nuxt 2 基础认知
1. 核心定位
Nuxt 2 是 Vue 2 生态的服务端渲染(SSR)框架,通过约定优于配置的方式,快速构建 SEO 友好、首屏性能优异的应用,核心价值:
- 解决 Vue SPA SEO 差(搜索引擎难以抓取动态内容)、首屏加载慢(需等待 JS 加载渲染)的问题;
- 内置路由、Vuex、构建优化等,减少配置成本;
- 支持 SSR、SSG(静态站点生成)、SPA 多种渲染模式。
2. 渲染模式
| 模式 |
说明 |
适用场景 |
| SSR(服务端渲染) |
每次请求在服务端生成 HTML,返回客户端 |
需 SEO、首屏性能要求高(电商、资讯、官网) |
| SSG(静态站点生成) |
构建时预生成所有 HTML,部署到 CDN |
内容不频繁变化(博客、文档、营销页) |
| SPA(单页应用) |
仅客户端渲染,与传统 Vue 2 项目一致 |
后台管理、内部系统(无需 SEO) |
二、项目创建与核心目录结构
1. 快速创建
1 2 3 4 5
| npx create-nuxt-app my-nuxt2-app cd my-nuxt2-app
npm run dev
|
2. 核心目录结构(约定优于配置)
1 2 3 4 5 6 7 8 9 10 11
| my-nuxt2-app/ ├── pages/ # 自动路由(核心) ├── components/ # 组件(需手动 import,Nuxt 2.13+ 支持自动导入) ├── layouts/ # 布局组件 ├── middleware/ # 路由中间件 ├── store/ # Vuex 状态管理(自动注册) ├── plugins/ # 插件(初始化 Vue 插件、全局方法) ├── assets/ # 静态资源(需 Webpack 处理,如 SCSS、图片) ├── static/ # 静态资源(直接复制,如 favicon.ico) ├── nuxt.config.js # 配置文件(核心) └── package.json
|
三、核心概念与重点功能
1. 自动路由(pages/ 目录)
Nuxt 2 基于 pages/ 目录文件自动生成 Vue Router 配置,无需手动定义路由:
- 基础路由:
pages/index.vue → /,pages/about.vue → /about;
- 动态路由:
pages/user/_id.vue → /user/123(参数通过 $route.params.id 获取);
- 嵌套路由:
pages/user/index.vue + pages/user/_id.vue → 需配合 <nuxt-child> 渲染子路由;
- 路由导航:用
<nuxt-link> 替代 <a>(客户端导航,避免页面刷新)。
示例:动态路由
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <!-- pages/user/_id.vue --> <template> <div> <h1>用户详情:{{ $route.params.id }}</h1> <nuxt-link to="/">返回首页</nuxt-link> </div> </template>
<script> export default { mounted() { console.log('用户ID:', this.$route.params.id) } } </script>
|
2. 数据获取(SSR 核心重点)
Nuxt 2 提供两个核心方法实现服务端预取数据(SSR 模式下在服务端执行,HTML 直接包含数据):
(1)asyncData(最常用,组件数据预取)
- 执行时机:组件创建之前(无
this),在服务端或客户端导航前调用;
- 作用:返回数据合并到组件
data,直接用于模板渲染;
- 适用场景:页面级数据获取(如列表页、详情页)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <!-- pages/posts.vue --> <template> <div> <h1>文章列表</h1> <div v-for="post in posts" :key="post.id">{{ post.title }}</div> </div> </template>
<script> import axios from 'axios'
export default { // asyncData 无 this,通过 context 获取路由、store 等 async asyncData({ $axios, params }) { // 推荐用 @nuxtjs/axios 模块(需安装配置) const { data: posts } = await $axios.get('https://api.example.com/posts') // 返回数据合并到 data return { posts } } } </script>
|
(2)fetch(Vuex 数据预取)
- 执行时机:与
asyncData 类似,但不返回数据;
- 作用:用于填充 Vuex store(有
this,指向组件实例);
- 适用场景:全局状态数据预取。
1 2 3 4 5 6 7 8 9
| <!-- pages/index.vue --> <script> export default { async fetch({ store, params }) { // 调用 Vuex action 填充状态 await store.dispatch('fetchPosts', params.id) } } </script>
|
(3)@nuxtjs/axios 模块(推荐)
Nuxt 2 常用的 HTTP 请求模块,需安装并配置:
1
| npm install @nuxtjs/axios
|
1 2 3 4 5 6 7
| export default { modules: ['@nuxtjs/axios'], axios: { baseURL: 'https://api.example.com' } }
|
3. 布局(layouts/ 目录)
用于统一页面结构(如头部、底部、侧边栏),默认布局为 layouts/default.vue:
1 2 3 4 5 6 7 8 9
| <!-- layouts/default.vue(默认布局) --> <template> <div> <header>网站头部</header> <!-- 页面内容通过 <nuxt /> 渲染 --> <nuxt /> <footer>网站底部</footer> </div> </template>
|
自定义布局:
1 2 3 4 5 6 7
| <!-- layouts/admin.vue(管理员布局) --> <template> <div> <aside>管理员侧边栏</aside> <nuxt /> </div> </template>
|
1 2 3 4 5 6
| <!-- pages/admin.vue(使用自定义布局) --> <script> export default { layout: 'admin' // 指定布局名称 } </script>
|
4. 中间件(middleware/ 目录)
用于路由拦截(如权限控制、重定向),分全局中间件和页面中间件:
1 2 3 4 5 6 7 8
| export default function ({ store, redirect, route }) { const isLogin = store.state.token if (!isLogin && route.path !== '/login') { return redirect('/login') } }
|
使用中间件:
1 2 3 4 5 6
| export default { router: { middleware: 'auth' } }
|
1 2 3 4 5 6
| <!-- pages/admin.vue(页面中间件,仅当前页面生效) --> <script> export default { middleware: 'auth' } </script>
|
5. Vuex 状态管理(store/ 目录)
Nuxt 2 内置 Vuex,store/ 目录下的文件自动生成模块,无需手动注册:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| export const state = () => ({ token: null, user: null })
export const mutations = { SET_TOKEN(state, token) { state.token = token }, SET_USER(state, user) { state.user = user } }
export const actions = { async nuxtServerInit({ commit }, { req }) { const token = req.headers.cookie?.token if (token) { commit('SET_TOKEN', token) const { data: user } = await this.$axios.get('/user') commit('SET_USER', user) } } }
|
1 2 3 4 5 6 7 8 9 10
| export const state = () => ({ list: [] })
export const mutations = { SET_LIST(state, list) { state.list = list } }
|
6. 插件(plugins/ 目录)
用于注册 Vue 插件、注入全局方法或属性(如 axios 拦截器、全局组件):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| export default function ({ $axios, redirect }) { $axios.onRequest(config => { const token = localStorage.getItem('token') if (token) { config.headers.Authorization = `Bearer ${token}` } return config })
$axios.onError(error => { if (error.response?.status === 401) { redirect('/login') } return Promise.reject(error) }) }
|
1 2 3 4
| export default { plugins: ['~/plugins/axios.js'] }
|
7. SEO 与元数据
通过页面的 head 方法配置页面 SEO,服务端渲染时直接注入 HTML:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <!-- pages/posts/_id.vue --> <script> export default { async asyncData({ $axios, params }) { const { data: post } = await $axios.get(`/posts/${params.id}`) return { post } }, // 动态配置页面元数据 head() { return { title: `${this.post.title} - 我的博客`, meta: [ { hid: 'description', name: 'description', content: this.post.summary } ] } } } </script>
|
四、配置文件(nuxt.config.js)
核心配置项:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| export default { head: { title: '我的 Nuxt 2 应用', meta: [ { charset: 'utf-8' }, { name: 'viewport', content: 'width=device-width, initial-scale=1' } ], link: [{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }] },
css: ['~/assets/scss/main.scss'],
plugins: ['~/plugins/axios.js'],
modules: ['@nuxtjs/axios'], axios: { baseURL: 'https://api.example.com' },
build: { extend(config, { isDev, isClient }) { } },
dev: process.env.NODE_ENV !== 'production' }
|
五、部署
1. SSR 模式部署
1 2 3 4
| npm run build
npm run start
|
需部署到 Node.js 环境(如 PM2 守护进程)。
2. SSG 静态站点部署
生成 dist/ 目录,直接部署到 CDN(如 Nginx、Vercel、Netlify)。
六、最佳实践
- 数据获取:页面级数据用
asyncData,Vuex 数据用 fetch,优先用 @nuxtjs/axios;
- 服务端/客户端差异:避免在服务端使用
window/document,用 process.client 判断(如 if (process.client) { window.scrollTo(0,0) });
- SEO 优化:页面用
head 方法动态配置 title、description,避免用 JS 渲染关键内容;
- 性能优化:图片放
assets/ 用 Webpack 压缩,大组件用 () => import('~/components/xxx.vue') 懒加载;
- 状态管理:全局状态用 Vuex,
nuxtServerInit 预取服务端初始数据。
总结
Nuxt 2 的核心是“让 Vue 2 SSR 开发更简单”,重点掌握:
- 自动路由、
asyncData/fetch 数据预取(SSR 核心);
- 布局、中间件、Vuex 状态管理;
- SEO 配置与部署方式。
Nuxt 2 生态成熟,是 Vue 2 项目实现 SSR 的首选方案,若需升级到 Vue 3 可迁移至 Nuxt 3。
Nuxt3
以下是 Nuxt.js(重点为 Nuxt 3,当前主流版本)的核心重点知识梳理,覆盖基础认知、核心特性、关键概念及最佳实践:
一、Nuxt.js 基础认知
1. 核心定位
Nuxt.js 是 Vue 生态的全栈/服务端渲染(SSR)框架,基于 Vue 3、Vite(默认)和 Nitro(服务端引擎),核心价值是:
- 开箱即用的 SSR:解决 Vue 单页应用(SPA)的 SEO 差、首屏加载慢 问题;
- 零配置开发:自动路由、组件自动导入、构建优化等,减少配置成本;
- 全栈能力:支持服务端 API 编写、中间件、静态站点生成(SSG)等多种渲染模式。
2. 渲染模式(核心选择)
Nuxt 3 支持 3 种主流渲染模式,可根据场景灵活切换:
| 模式 |
说明 |
适用场景 |
| SSR(服务端渲染) |
每次请求在服务端生成 HTML,返回给客户端 |
需 SEO、首屏性能要求高的场景(如电商、资讯) |
| SSG(静态站点生成) |
构建时预生成所有 HTML,部署到 CDN |
内容不频繁变化的场景(如博客、文档) |
| SPA(单页应用) |
仅客户端渲染,与传统 Vue 项目一致 |
后台管理系统、无需 SEO 的内部系统 |
二、项目创建与核心目录结构
1. 快速创建(Nuxt 3)
1 2 3 4 5 6 7
| npx nuxi init my-nuxt-app cd my-nuxt-app
npm install
npm run dev
|
2. 核心目录结构(重点)
Nuxt 3 采用约定优于配置,目录结构决定功能:
1 2 3 4 5 6 7 8 9 10 11
| my-nuxt-app/ ├── pages/ # 自动路由(核心) ├── components/ # 自动导入的组件 ├── composables/ # 自动导入的组合式函数 ├── server/ # 服务端代码(API、中间件) ├── layouts/ # 布局组件 ├── middleware/ # 路由中间件 ├── plugins/ # 插件(初始化第三方库) ├── assets/ # 静态资源(需构建处理,如 SCSS) ├── public/ # 静态资源(直接复制,如 favicon) └── nuxt.config.ts # 配置文件(核心)
|
三、核心概念与重点功能
1. 自动路由(pages/ 目录)
Nuxt 3 基于 pages/ 目录下的文件自动生成路由,无需手动配置 Vue Router:
- 基础路由:
pages/index.vue → /,pages/about.vue → /about;
- 动态路由:
pages/user/[id].vue → /user/123(通过 route.params.id 获取参数);
- 嵌套路由:
pages/user/index.vue + pages/user/[id].vue → 嵌套结构;
- 路由导航:用
<NuxtLink> 替代 <a> 标签(客户端导航,性能更好)。
示例:动态路由
1 2 3 4 5 6 7 8 9 10
| <!-- pages/user/[id].vue --> <script setup> const route = useRoute() console.log('用户ID:', route.params.id) // 获取动态参数 </script>
<template> <div>用户详情页:{{ route.params.id }}</div> <NuxtLink to="/">返回首页</NuxtLink> </template>
|
2. 组件自动导入(components/ 目录)
components/ 目录下的组件无需 import 即可直接使用,支持嵌套目录:
- 基础组件:
components/MyButton.vue → 直接用 <MyButton />;
- 嵌套组件:
components/user/UserCard.vue → 用 <UserCard />(自动扁平化)或 <UserUserCard />(完整路径)。
示例:自动导入组件
1 2 3 4 5
| <!-- pages/index.vue --> <template> <!-- 无需 import,直接使用 components/MyButton.vue --> <MyButton text="点击我" /> </template>
|
3. 组合式函数自动导入(composables/ 目录)
composables/ 目录下的组合式函数(复用逻辑)自动导入,类似 VueUse 的用法:
1 2 3 4 5 6
| export function useCounter() { const count = ref(0) const increment = () => count.value++ return { count, increment } }
|
1 2 3 4 5 6 7 8 9 10
| <!-- pages/index.vue --> <script setup> // 无需 import,直接使用 useCounter const { count, increment } = useCounter() </script>
<template> <div>计数:{{ count }}</div> <button @click="increment">+1</button> </template>
|
4. 数据获取(核心重点)
Nuxt 3 提供 3 种核心数据获取方式,支持服务端预取(SSR 模式下在服务端执行,返回 HTML 时已包含数据):
(1)useFetch(最常用,简化版)
自动处理请求取消、重复请求,适合简单场景:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <script setup> // 服务端预取数据,返回给客户端 const { data: posts, error } = await useFetch('/api/posts')
if (error.value) { console.error('请求失败:', error.value) } </script>
<template> <div v-if="posts"> <div v-for="post in posts" :key="post.id">{{ post.title }}</div> </div> <div v-else-if="error">加载失败</div> <div v-else>加载中...</div> </template>
|
(2)useAsyncData(更灵活,自定义请求)
配合 $fetch 使用,适合复杂请求(如自定义 headers、错误处理):
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <script setup> const { data: user, pending, refresh } = await useAsyncData('user', () => $fetch('https://api.example.com/user/1') )
// 手动刷新数据 const handleRefresh = () => refresh() </script>
<template> <div v-if="pending">加载中...</div> <div v-else-if="user">{{ user.name }}</div> <button @click="handleRefresh">刷新</button> </template>
|
(3)$fetch(基于 ofetch 的请求库)
Nuxt 3 内置的请求库,替代 axios,支持服务端/客户端通用:
1 2 3 4 5 6 7 8
| const data = await $fetch('/api/posts')
const user = await $fetch('/api/user', { method: 'POST', body: { name: '张三' } })
|
5. SEO 与元数据管理(SSR 核心价值)
Nuxt 3 提供 useHead 和 useSeoMeta 管理页面元数据,服务端渲染时直接注入 HTML:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <script setup> // 基础元数据 useHead({ title: '首页 - 我的Nuxt应用', meta: [ { name: 'description', content: '这是Nuxt应用的首页' } ] })
// SEO 优化(更简洁的写法) useSeoMeta({ title: '首页 - 我的Nuxt应用', description: '这是Nuxt应用的首页', ogTitle: 'Nuxt应用首页', ogDescription: '分享给朋友的描述' }) </script>
|
6. 服务端 API(server/ 目录)
Nuxt 3 内置 Nitro 服务端引擎,可直接在 server/api/ 目录下编写 API,无需额外搭建后端服务:
1 2 3 4 5 6 7 8 9
| export default defineEventHandler(async () => { const posts = [ { id: 1, title: '第一篇文章' }, { id: 2, title: '第二篇文章' } ] return posts })
|
1 2 3 4 5
| export default defineEventHandler(async (event) => { const id = getRouterParam(event, 'id') return { id, name: `用户${id}` } })
|
7. 中间件(middleware/ 目录)
用于路由拦截(如权限控制、重定向),支持全局中间件和页面中间件:
1 2 3 4 5 6 7
| export default defineNuxtRouteMiddleware((to, from) => { const token = useCookie('token') if (!token.value) { return navigateTo('/login') } })
|
1 2 3 4 5 6 7 8 9 10 11
| <!-- pages/admin.vue(使用中间件) --> <script setup> // 应用 auth 中间件 definePageMeta({ middleware: 'auth' }) </script>
<template> <div>管理员页面(需登录)</div> </template>
|
四、配置与部署
1. 核心配置(nuxt.config.ts)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| export default defineNuxtConfig({ devtools: { enabled: true }, app: { head: { title: '我的Nuxt应用', meta: [{ name: 'charset', content: 'utf-8' }] } }, modules: ['@nuxtjs/tailwindcss'], runtimeConfig: { apiSecret: 'secret', public: { apiBase: '/api' } } })
|
2. 部署方式
Nuxt 3 支持多种部署方式,根据渲染模式选择:
- Node.js 部署:
npm run build → node .output/server/index.mjs(适合 SSR 模式);
- 静态站点部署:
npm run generate → 生成 dist/ 目录,部署到 CDN(适合 SSG 模式);
- 边缘部署:直接部署到 Vercel、Netlify(自动适配,零配置)。
五、最佳实践
- 合理选择渲染模式:SEO 优先选 SSR,内容静态选 SSG,内部系统选 SPA;
- 数据获取优化:优先用
useFetch,复杂场景用 useAsyncData,避免客户端重复请求;
- 组件拆分:通用组件放
components/,复用逻辑放 composables/,提升代码可维护性;
- 性能优化:用
<NuxtImg> 优化图片加载,开启 nuxt.config.ts 中的构建缓存;
- TypeScript 支持:Nuxt 3 原生支持 TS,建议全程用 TS 编写,提升类型安全。
总结
Nuxt.js 的核心是“让 Vue 开发更简单、更强大”,重点掌握:
- 自动路由、组件/组合式函数自动导入(零配置开发);
- 数据获取(
useFetch、useAsyncData)与 SEO 管理(useSeoMeta);
- 服务端 API 编写(
server/ 目录)与中间件;
- 渲染模式选择与部署方式。
Nuxt 3 基于 Vue 3 + Vite,性能和开发体验都大幅提升,是 Vue 生态中 SSR/全栈开发的首选框架。