服务端渲染Nuxtjs重点知识

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
# 使用 create-nuxt-app 脚手架
npx create-nuxt-app my-nuxt2-app
cd my-nuxt2-app
# 启动开发服务器(默认 http://localhost:3000)
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
// nuxt.config.js
export default {
modules: ['@nuxtjs/axios'],
axios: {
baseURL: 'https://api.example.com' // 配置基础 URL
}
}

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
// middleware/auth.js(权限中间件)
export default function ({ store, redirect, route }) {
// 判断是否登录(示例:从 store 获取 token)
const isLogin = store.state.token
if (!isLogin && route.path !== '/login') {
return redirect('/login') // 未登录重定向到登录页
}
}

使用中间件

1
2
3
4
5
6
// nuxt.config.js(全局中间件,所有路由生效)
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 内置 Vuexstore/ 目录下的文件自动生成模块,无需手动注册:

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
// store/index.js(根模块)
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 = {
// 服务端预取用户信息(nuxtServerInit 仅在服务端执行)
async nuxtServerInit({ commit }, { req }) {
// 从请求中获取 token(示例)
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
// store/posts.js(子模块,自动命名为 posts)
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
// plugins/axios.js(axios 拦截器)
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
// nuxt.config.js(注册插件)
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
css: ['~/assets/scss/main.scss'],

// 插件
plugins: ['~/plugins/axios.js'],

// 模块
modules: ['@nuxtjs/axios'],
axios: {
baseURL: 'https://api.example.com'
},

// 构建配置
build: {
// 扩展 Webpack 配置
extend(config, { isDev, isClient }) {
// 示例:添加 loader
}
},

// 开发环境配置
dev: process.env.NODE_ENV !== 'production'
}

五、部署

1. SSR 模式部署

1
2
3
4
# 构建生产版本
npm run build
# 启动服务
npm run start

需部署到 Node.js 环境(如 PM2 守护进程)。

2. SSG 静态站点部署

1
2
# 预生成所有 HTML
npm run generate

生成 dist/ 目录,直接部署到 CDN(如 Nginx、Vercel、Netlify)。

六、最佳实践

  1. 数据获取:页面级数据用 asyncData,Vuex 数据用 fetch,优先用 @nuxtjs/axios
  2. 服务端/客户端差异:避免在服务端使用 window/document,用 process.client 判断(如 if (process.client) { window.scrollTo(0,0) });
  3. SEO 优化:页面用 head 方法动态配置 title、description,避免用 JS 渲染关键内容;
  4. 性能优化:图片放 assets/ 用 Webpack 压缩,大组件用 () => import('~/components/xxx.vue') 懒加载;
  5. 状态管理:全局状态用 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
# 启动开发服务器(默认 http://localhost:3000)
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
// composables/useCounter.ts
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 提供 useHeaduseSeoMeta 管理页面元数据,服务端渲染时直接注入 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
// server/api/posts.get.ts
export default defineEventHandler(async () => {
// 模拟数据库查询
const posts = [
{ id: 1, title: '第一篇文章' },
{ id: 2, title: '第二篇文章' }
]
return posts
})
1
2
3
4
5
// server/api/user/[id].get.ts(动态路由 API)
export default defineEventHandler(async (event) => {
const id = getRouterParam(event, 'id')
return { id, name: `用户${id}` }
})

7. 中间件(middleware/ 目录)

用于路由拦截(如权限控制、重定向),支持全局中间件页面中间件

1
2
3
4
5
6
7
// middleware/auth.ts(页面中间件)
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 buildnode .output/server/index.mjs(适合 SSR 模式);
  • 静态站点部署npm run generate → 生成 dist/ 目录,部署到 CDN(适合 SSG 模式);
  • 边缘部署:直接部署到 Vercel、Netlify(自动适配,零配置)。

五、最佳实践

  1. 合理选择渲染模式:SEO 优先选 SSR,内容静态选 SSG,内部系统选 SPA;
  2. 数据获取优化:优先用 useFetch,复杂场景用 useAsyncData,避免客户端重复请求;
  3. 组件拆分:通用组件放 components/,复用逻辑放 composables/,提升代码可维护性;
  4. 性能优化:用 <NuxtImg> 优化图片加载,开启 nuxt.config.ts 中的构建缓存;
  5. TypeScript 支持:Nuxt 3 原生支持 TS,建议全程用 TS 编写,提升类型安全。

总结

Nuxt.js 的核心是“让 Vue 开发更简单、更强大”,重点掌握:

  • 自动路由、组件/组合式函数自动导入(零配置开发);
  • 数据获取(useFetchuseAsyncData)与 SEO 管理(useSeoMeta);
  • 服务端 API 编写(server/ 目录)与中间件;
  • 渲染模式选择与部署方式。

Nuxt 3 基于 Vue 3 + Vite,性能和开发体验都大幅提升,是 Vue 生态中 SSR/全栈开发的首选框架。


服务端渲染Nuxtjs重点知识
http://example.com/20260204-服务端渲染Nuxtjs重点知识/
作者
csorz
发布于
2026年2月4日
许可协议