文章目录
NuxtJS 学习笔记
一、NuxtJS 是什么?
NuxtJS 是基于 Vue.js 的开源框架,专为构建高性能、SEO 友好的现代 Web 应用设计。它集成了 Vue 生态的核心工具(Vue Router、Vuex/Pinia、Vue 编译器等),并提供了服务端渲染(SSR)、**静态站点生成(SSG)**等关键能力,解决了纯 Vue 单页应用(SPA)首屏加载慢、SEO 不友好的痛点。
核心定位
- 不是替代 Vue,而是 增强 Vue 的“上层框架”
- 专注于“应用工程化”,简化 Vue 项目的配置、构建、部署流程
- 支持多渲染模式:SSR(服务端渲染)、SSG(静态生成)、CSR(客户端渲染)、ISR(增量静态再生)
二、NuxtJS 核心特点
1. 开箱即用的渲染方案
- SSR(服务端渲染):页面在服务端渲染成 HTML 后再返回客户端,首屏加载快、SEO 友好
- SSG(静态生成):构建时预渲染所有页面为静态 HTML,部署到 CDN 即可,性能极致
- 自动切换:无需手动配置复杂的渲染逻辑,Nuxt 内部优化渲染流程
2. 零配置路由系统
- 基于文件系统的路由:
pages/目录下的.vue文件自动生成路由(无需手动写 Vue Router 配置) - 支持动态路由(如
pages/user/[id].vue)、嵌套路由、路由守卫(middleware/目录)
3. 内置优化与配置
- 自动代码分割、Tree-shaking,减少打包体积
- 内置 CSS 预处理支持(Sass/SCSS、Less 等,无需额外装 loader)
- 自动处理静态资源(图片、字体等),支持自动优化图片尺寸和格式
- 内置 ESLint、Prettier 配置,规范代码风格
4. 强大的 SEO 支持
- 服务端渲染输出完整 HTML,搜索引擎可直接抓取内容
- 内置
head配置(标题、元标签、OG 标签),可在页面或全局统一设置 - 支持 JSON-LD 结构化数据,提升 SEO 排名
5. 模块生态丰富
- 官方模块:
Pinia(状态管理)、I18n(国际化)、Auth(身份认证)、Content(内容管理)等 - 第三方模块:支持集成
Tailwind CSS、Element Plus、Axios等常用工具
6. 开发体验友好
- 热模块替换(HMR):修改代码实时更新,无需刷新页面
- 错误页面自动生成:404、500 等页面可自定义
- 内置调试工具,支持 VS Code 语法提示
三、NuxtJS 安装步骤
前提条件
- Node.js 版本 ≥ 18.x(Nuxt 3 最低要求,推荐 18.x LTS 或 20.x LTS)
- 包管理器:npm、yarn 或 pnpm(推荐 npm 或 pnpm)
推荐安装方式(Nuxt 3,官方首选)
Nuxt 3 推荐使用 nuxi 命令行工具(官方维护,稳定无网络坑):
-
检查 Node 版本
node -v # 输出 v18.x 或更高版本 -
创建项目(指定项目名,如
nuxt-demo)npx nuxi init nuxt-demo -
进入项目目录
cd nuxt-demo -
安装依赖
npm install # 或 yarn install、pnpm install -
启动开发服务器
npm run dev # 启动后访问 http://localhost:3000
兼容安装(Nuxt 2,旧项目使用)
若需兼容 Nuxt 2,使用 create-nuxt-app(需解决网络问题,参考前文):
# 安装并创建 Nuxt 2 项目
npx create-nuxt-app@2 nuxt2-demo
安装常见问题解决
- 网络超时/模板下载失败:
- 切换 npm 镜像源:
npm config set registry https://registry.npmmirror.com - 修改 Hosts 映射
raw.githubusercontent.com(参考前文方案二)
- 切换 npm 镜像源:
- 依赖安装失败:
- 清除 npm 缓存:
npm cache clean --force - 升级包管理器:
npm install -g npm@latest
- 清除 npm 缓存:
四、NuxtJS 基础使用
1. 项目目录结构(Nuxt 3 核心目录)
nuxt-demo/
├── app.vue # 根组件(入口文件)
├── pages/ # 页面目录(自动生成路由)
│ ├── index.vue # 首页(对应 / 路由)
│ └── about.vue # 关于页(对应 /about 路由)
├── components/ # 公共组件目录(自动导入,无需 import)
├── composables/ # 组合式函数目录(自动导入)
├── nuxt.config.ts # Nuxt 配置文件(核心配置)
└── package.json # 依赖配置
2. 核心功能使用示例
(1)页面与路由(自动路由)
Nuxt 最核心的特性之一,无需配置 Vue Router,文件即路由:
pages/index.vue→ 路由/(首页)pages/about.vue→ 路由/about(关于页)pages/user/[id].vue→ 动态路由/user/123(通过$route.params.id获取参数)
页面组件示例(pages/index.vue):
<template>
<div class="container">
<h1>Hello Nuxt 3!</h1>
<!-- 路由跳转(使用 NuxtLink,类似 Vue Router 的 router-link) -->
<NuxtLink to="/about">前往关于页</NuxtLink>
</div>
</template>
<script setup>
// 无需导入 NuxtLink,Nuxt 自动全局注册
</script>
<style scoped>
.container {
padding: 2rem;
text-align: center;
}
</style>
(2)组件使用(自动导入)
components/ 目录下的组件无需手动 import,直接在页面中使用:
-
创建组件:
components/HelloWorld.vue<template> <p>这是公共组件:{{ msg }}</p> </template> <script setup> const props = defineProps({ msg: String }) </script> -
在页面中使用(pages/index.vue):
<template> <div class="container"> <h1>Hello Nuxt 3!</h1> <HelloWorld msg="Nuxt 组件自动导入真方便~" /> </div> </template>
(3)数据请求(内置 useFetch)
Nuxt 3 内置 useFetch 组合式函数,支持服务端/客户端数据请求(自动处理 SSR/SSG 数据预取):
<!-- pages/users.vue -->
<template>
<div>
<h2>用户列表</h2>
<ul v-if="users.length">
<li v-for="user in users" :key="user.id">{{ user.name }}</li>
</ul>
<p v-else>加载中...</p>
</div>
</template>
<script setup>
// 服务端预取数据,页面渲染时已包含数据(SEO 友好)
const { data: users } = await useFetch('https://jsonplaceholder.typicode.com/users')
</script>
(4)全局配置(nuxt.config.ts)
核心配置文件,用于配置路由、CSS、模块、服务器等:
// nuxt.config.ts
export default defineNuxtConfig({
// 应用基础配置
app: {
head: {
title: '我的 Nuxt 应用', // 全局页面标题
meta: [
{ name: 'description', content: 'NuxtJS 学习笔记示例' } // SEO 描述
]
}
},
// 全局 CSS(无需在组件中导入)
css: ['~/assets/css/global.css'],
// 模块配置(如集成 Tailwind CSS)
modules: ['@nuxtjs/tailwindcss']
})
(5)状态管理(Pinia,Nuxt 3 推荐)
-
安装 Pinia 模块:
npm install @pinia/nuxt -
在
nuxt.config.ts中注册:export default defineNuxtConfig({ modules: ['@pinia/nuxt'] }) -
创建 Store:
stores/counter.tsimport { defineStore } from 'pinia' export const useCounterStore = defineStore('counter', { state: () => ({ count: 0 }), actions: { increment() { this.count++ } } }) -
在页面中使用:
<template> <div> <p>计数:{{ counter.count }}</p> <button @click="counter.increment()">+1</button> </div> </template> <script setup> const counter = useCounterStore() </script>
3. 运行与构建命令
| 命令 | 作用 |
|---|---|
npm run dev | 启动开发服务器(热更新,默认 3000 端口) |
npm run build | 构建生产版本(根据配置生成 SSR/SSG 资源) |
npm run preview | 预览构建后的生产版本 |
npm run generate | 生成静态站点(SSG,输出 dist/ 目录) |
五、获取MySQL数据
5.1 安装 MySQL 依赖
yarn add mysql2 -S
5.2 封装数据库连接(复用 + 连接池)
在项目根目录创建 server/utils/db.js(Nuxt 服务端工具目录),封装数据库连接池(避免频繁创建连接):
// server/utils/db.js
import mysql from 'mysql2/promise';
// 数据库配置(请替换为你的 MySQL 地址、账号、密码)
const DB_CONFIG = {
host: 'localhost', // 本地 MySQL 默认为 localhost,远程需填服务器 IP
user: 'root', // 你的 MySQL 用户名(默认 root)
password: '123456',// 你的 MySQL 密码(安装时设置的密码)
database: 'nuxt_echart_db', // 第一步创建的数据库名
port: 3306, // MySQL 默认端口 3306
waitForConnections: true,
connectionLimit: 10, // 最大连接数
queueLimit: 0
};
// 创建连接池
const pool = mysql.createPool(DB_CONFIG);
// 封装查询方法(全局复用)
export async function query(sql, params = []) {
const [rows] = await pool.execute(sql, params);
return rows;
}
5.3 开发 Nuxt API 接口(服务端)
Nuxt 4 内置 API 路由(无需额外配置服务器),在 server/api 目录下创建接口文件,用于查询 MySQL 数据并返回给前端。
创建接口文件:server/api/line-chart-data.get.js
// server/api/line-chart-data.get.js
// 接口地址:http://localhost:3000/api/line-chart-data(GET 请求)
import { query } from '../utils/db';
export default defineEventHandler(async (event) => {
try {
// 查询所有数据(按时间排序,确保 x 轴顺序正确)
const sql = 'SELECT date, golden_lake, supply_chain, unknown_vuln, malicious_code, copyright, crowdsourced, trusted_repair FROM echart_line_data ORDER BY date ASC';
const data = await query(sql);
// 整理数据格式(适配前端 ECharts 配置)
const result = {
xAxisData: data.map(item => item.date), // x 轴时间数据
seriesData: [
{ name: '金银湖大模型漏洞检测', data: data.map(item => item.golden_lake) },
{ name: '供应链漏洞检测', data: data.map(item => item.supply_chain) },
{ name: '未知漏洞检测', data: data.map(item => item.unknown_vuln) },
{ name: '恶意代码投毒检测', data: data.map(item => item.malicious_code) },
{ name: '代码版权检测', data: data.map(item => item.copyright) },
{ name: '众测漏洞检测', data: data.map(item => item.crowdsourced) },
{ name: '可信修复', data: data.map(item => item.trusted_repair) }
]
};
// 返回数据给前端(200 成功状态)
return {
code: 200,
message: '数据获取成功',
data: result
};
} catch (error) {
// 错误处理(打印日志 + 返回错误信息)
console.error('接口错误:', error);
return {
code: 500,
message: '数据获取失败',
error: error.message
};
}
});
测试接口是否可用
- 启动 Nuxt 项目:yarn dev;
- 浏览器访问:
http://localhost:3000/api/line-chart-data; - 若返回如下 JSON,说明接口正常(数据与 SQL 插入的一致):
{
"code": 200,
"message": "数据获取成功",
"data": {
"xAxisData": ["24.09","24.10","24.11","24.12","25.01","25.02","25.03"],
"seriesData": [
{"name":"金银湖大模型漏洞检测","data":[310,190,360,400,410,300,220]},
// 其他 6 个系列数据...
]
}
}
六、Axios全局注册
6.1 安装axios
# 安装 Axios(Nuxt 4 兼容所有最新版本)
yarn add axios -S
6.2 全局注册 Axios(客户端插件)
在 app/plugins/ 目录下创建 axios.client.ts(.client 后缀确保仅客户端使用,避免服务端报错),全局配置 Axios 并提供给所有组件:
// app/plugins/axios.client.ts
import { defineNuxtPlugin } from "#app";
import axios from "axios";
export default defineNuxtPlugin((nuxtApp) => {
// 1. 创建 Axios 实例,配置基础路径、超时等(按需调整)
const axiosInstance = axios.create({
baseURL: import.meta.env.VITE_API_BASE_URL || "http://localhost:3000", // 基础路径(可通过环境变量配置)
timeout: 5000, // 超时时间(5秒)
headers: {
"Content-Type": "application/json", // 默认请求头
},
});
// 2. 可选:添加请求拦截器(如添加 Token、统一请求参数)
axiosInstance.interceptors.request.use(
(config) => {
// 示例:添加登录 Token(从 localStorage 读取,按需修改)
const token = localStorage.getItem("token");
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
},
(error) => Promise.reject(error)
);
// 3. 可选:添加响应拦截器(统一处理错误、解析数据)
axiosInstance.interceptors.response.use(
(response) => {
// 直接返回响应体(Axios 已自动解析 JSON),无需手动 json()
return response.data;
},
(error) => {
// 统一错误处理(如 401 未授权、500 服务器错误)
console.error("Axios 请求失败:", error.message);
return Promise.reject(error);
}
);
// 4. 全局提供 Axios 实例:组件中可通过 this.$axios 或 useNuxtApp() 获取
nuxtApp.provide("axios", axiosInstance);
});
baseURL配置:默认指向你的 Nuxt 服务端接口地址(http://localhost:3000),后续调用接口可省略基础路径(如 /api/line-chart-data 直接写成 api/line-chart-data);- 拦截器:可选但推荐添加,统一处理
Token、错误,减少组件内重复代码; - 全局提供:通过
nuxtApp.provide("axios", instance),组件中可全局访问,无需局部导入。
6.3组件中调用 Axios(全局使用)
<!-- app/components/EchartsLine.client.vue -->
<template>
<div ref="chartRef" class="chart-container"></div>
</template>
<script>
import * as echarts from "echarts";
export default {
name: "EchartsLine",
data() {
return {
chartRef: null,
chartData: null, // 存储接口返回数据
};
},
mounted() {
this.fetchChartData(); // 组件挂载时请求数据
},
methods: {
// 调用 Axios 获取接口数据
async fetchChartData() {
try {
// 全局调用 Axios(无需导入,直接 this.$axios)
const res = await this.$axios.get("api/line-chart-data"); // 省略 baseURL,直接写相对路径
// 直接使用解析后的数据(Axios 已自动处理 JSON)
if (res.code === 200) {
this.chartData = res.data;
this.initECharts(); // 初始化 ECharts
} else {
console.error("数据获取失败:", res.message);
}
} catch (error) {
console.error("接口请求失败:", error.message);
}
},
// 初始化 ECharts
initECharts() {
if (!this.chartRef || !this.chartData) return;
const chart = echarts.init(this.chartRef);
// ECharts 配置项(使用 this.chartData)
const option = {
title: { text: "折线图示例", color: "#CEF4FD" },
xAxis: {
type: "category",
data: this.chartData.xData, // 接口返回的 x 轴数据
axisLine: { lineStyle: { color: "#CEF4FD" } },
axisLabel: { color: "#CEF4FD" },
},
yAxis: {
type: "value",
axisLine: { lineStyle: { color: "#CEF4FD" } },
axisLabel: { color: "#CEF4FD" },
},
series: [
{
data: this.chartData.seriesData, // 接口返回的系列数据
type: "line",
lineStyle: { color: "#6dd0e3" },
itemStyle: { color: "#6dd0e3" },
},
],
backgroundColor: "transparent",
};
chart.setOption(option);
// 窗口resize自适应
window.addEventListener("resize", () => chart.resize());
},
},
};
</script>
<style scoped>
.chart-container {
width: 100%;
height: 400px;
}
</style>
七、Nuxt 应用部署服务器
入口点
使用 Node 服务器预设运行 nuxt build 时,结果将是一个可直接运行的 Node 服务器入口点。
node .output/server/index.mjs
这将启动您的生产 Nuxt 服务器,默认监听 3000 端口。
它支持以下运行时环境变量:
NITRO_PORT或PORT(默认为 3000)NITRO_HOST或HOST(默认为 ‘0.0.0.0’)NITRO_SSL_CERT和NITRO_SSL_KEY- 如果两者都存在,将以HTTPS模式启动服务器。在绝大多数情况下,除了测试外不应使用此选项,并且 Nitro 服务器应在终止 SSL 的反向代理(如 nginx 或 Cloudflare)后面运行。
PM2
PM2(进程管理器 2)是在您的服务器或虚拟机上托管 Nuxt 应用程序的快速简便解决方案。
要使用 pm2,请在跟目录创建并使用 ecosystem.config.js:
module.exports = {
apps: [
{
name: 'NuxtAppName',
port: '3000',
exec_mode: 'cluster',
instances: 'max',
script: './.output/server/index.mjs'
}
]
}
将以下文件 / 文件夹上传到服务器的 /www/nuxt3-project 目录(用 Xftp 或 scp 命令):
- .output/(Nuxt3 打包产物,核心);
ecosystem.config.js(PM2 配置文件);- .env(可选,环境变量配置,优先级低于 PM2 的 env);
- logs/(日志文件夹)。
# 1. 用 PM2 启动服务(读取 ecosystem.config.cjs 配置)
pm2 start
# 2. 验证服务状态(关键!确保启动成功)
pm2 list
// 后续命令
pm2 restart Nuxt3-App # 重启服务(更新代码/配置后用)
pm2 stop Nuxt3-App # 停止服务
pm2 logs Nuxt3-App # 查看实时日志(排查错误)
pm2 delete Nuxt3-App # 删除服务
pm2 save # 保存当前 PM2 配置(服务器重启后自动恢复)
pm2 startup # 设置 PM2 开机自启(服务器重启后自动启动服务)
集群模式
您可以使用 NITRO_PRESET=node_cluster 来利用 Node.js cluster 模块实现多进程性能。
默认情况下,工作负载会以轮询策略分配给工作进程。
静态托管
将 Nuxt 应用程序部署到任何静态托管服务有两种方式:
- 使用
ssr: true的静态站点生成 (SSG) 在构建时预渲染应用程序的路由。(这是运行 nuxt generate 时的默认行为。)它还将生成 /200.html 和 /404.html 单页应用回退页面,这些页面可以在客户端渲染动态路由或 404 错误(尽管您可能需要在静态主机上配置此功能)。 - 或者,您可以使用
ssr: false预渲染您的站点(静态单页应用)。这将生成包含空<div id="__nuxt"></div>的 HTML 页面,您的 Vue 应用通常会在此处渲染。这样会失去预渲染站点的许多 SEO 优势,因此建议改用<ClientOnly>来包装站点中无法在服务器端渲染的部分(如果有的话)。
仅客户端渲染
如果您不想预渲染路由,另一种使用静态托管的方法是在 nuxt.config 文件中将 ssr 属性设置为 false。然后,nuxt generate 命令将输出一个 .output/public/index.html 入口点和 JavaScript 捆绑包,就像经典的客户端 Vue.js 应用程序一样。
// nuxt.config.ts
export default defineNuxtConfig({
ssr: false
})
1070

被折叠的 条评论
为什么被折叠?



