一、安装node
nodejs官网:Node.js --- Run JavaScript Everywhere
安装完成后查看nodejs版本判断时候安装成功
javascript
node -v
二、创建node项目
1、首先新建一个文件夹,名字任起,如wx-server,然后就可以初始化node项目及安装所需的一些工具了。
javascript
//初始化 Node 项目
npm init -y
//装后端需要的工具
npm i express axios cors body-parser
三、nodejs的基本操作
1、nodejs运行指定文件
javascript
//node 文件名 (需含后缀,并且这不会触发热更新)
例:node index.js
//若想触发热更新需安装nodemon插件
安装命令:
npm i nodemon -g
此时就可使用nodemon 命令运行指定文件
例:nodemon index.js
四、如何使用nodejs搭建服务器
方式一:使用 Node.js 原生 HTTP(最基础 ✅)
1️⃣ 创建 server.js
javascript
//引入 Node.js 内置的 http模块
const http = require('http')
//创建一个 HTTP 服务器,其中 req 与 res 是请求对象和响应对象
const server = http.createServer((req, res) => {
//设置状态码 200,并返回响应头
res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' })
//返回数据并结束响应
res.end('你好,Node.js')
})
const PORT = 3000
//监听 3000 端口
server.listen(PORT, () => {
console.log(服务器启动成功:http://localhost:${PORT})
})
2️⃣ 启动服务器
javascript
nodemon server.js
浏览器访问:
javascript
http://localhost:3000
详细示例:
javascript
// 第一步:引入 Node.js 内置模块
// http 模块:用来创建服务器(必须)
const http = require('http')
// url 模块:用来解析浏览器地址栏里的 URL
const url = require('url')
// querystring 模块:用来解析 POST 表单数据
const querystring = require('querystring')
// 第二步:创建 HTTP 服务器
//http.createServer() 用来创建一个服务器,其中req是请求参数、res是响应参数
const server = http.createServer((req, res) => {
// 第三步:解析请求信息
/*
req.url 是浏览器访问的路径
例如:http://localhost:3000/getinfo?id=1
使用 url.parse() 解析后:
pathname = '/getinfo'
query = { id: '1' }
*/
const parsedUrl = url.parse(req.url, true)
const pathname = parsedUrl.pathname // 请求路径
const query = parsedUrl.query // GET 请求参数
const method = req.method // 请求方式(GET 或 POST)
// 第四步:设置响应头(防止中文乱码)
/*
告诉浏览器:
1. 返回的是普通文本
2. 使用 UTF-8 编码(否则中文会乱码)
*/
res.setHeader('Content-Type', 'text/plain;charset=utf-8')
// 第五步:路由判断(重点!)
/*
路由 = 根据不同的 URL 和请求方式,做不同的事情
*/
// ① 处理 GET 请求
if (method === 'GET' && pathname === '/getinfo') {
console.log('GET 参数:', query)
// 返回响应给浏览器
res.end('GET 请求成功')
return
}
// ② 处理 POST 请求
if (method === 'POST' && pathname === '/postinfo') {
let postData = ''
/*
POST 数据是"分段"传过来的
我们需要监听两个事件:
1. data :收到数据
2. end :数据接收完成
*/
// 每次收到一小段数据
req.on('data', chunk => {
postData += chunk.toString()
})
// 所有数据接收完成
req.on('end', () => {
/*
把字符串转换成对象
例如:username=admin&password=123
转换后:{ username: 'admin', password: '123' }
*/
const body = querystring.parse(postData)
console.log('POST 参数:', body)
// 返回 JSON 数据
res.setHeader('Content-Type', 'application/json;charset=utf-8')
res.end(JSON.stringify({
code: 200,
msg: 'POST 成功',
data: body
}))
})
return
}
// 第六步:404 处理(接口不存在)
res.statusCode = 404
res.end('404 Not Found')
})
// 第七步:启动服务器
/*
服务器必须监听一个端口
端口就像"门牌号"
*/
const PORT = 3000
server.listen(PORT, () => {
console.log('服务器启动:http://localhost:3000')
})
疑问解答:
1、http模块是干嘛的?
http模块是 Node.js 用来创建 Web 服务器的核心模块。
有了它,你才可以:创建服务器、监听端口、接收 HTTP 请求、返回响应
✅ 没有 http模块,Node.js 本身不能当服务器用。
2、res.writeHead()中的第二个参数是什么?Content-Type是什么?
第二个参数是响应头。告诉客户端:返回的数据是什么类型,text/plain指纯文本。text/html指html页面。application/json指JSON数据。image/png指图片。
javascript
res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' })
3、如果不写 writeHead会怎样?
Node.js 会:默认状态码:200、默认 Content-Type: text/plain、默但中文很容易会乱码。
方式二:使用 Express(✅ 企业级推荐)
1️⃣ 安装 Express
javascript
npm install express
2️⃣ 创建 app.js
javascript
//引入 Express 框架
const express = require('express')
//创建一个 Express 应用实例
const app = express()
// 中间件(解析 JSON),即让服务器能够自动解析前端发送的 JSON 数据
app.use(express.json())
// 路由(这里的意思是当用户访问根路径 /时,执行对应的处理函数并返回数据)
app.get('/', (req, res) => {
res.send('你好 Express!')
})
// 创建GET 接口
app.get('/api/user', (req, res) => {
res.json({
code: 200,
data: { name: '张三', age: 18 }
})
})
// 创建POST 接口
app.post('/api/login', (req, res) => {
const { username } = req.body
res.json({
code: 200,
msg: 欢迎回来,${username}
})
})
//启动服务器并监听指定的端口(3000),等待客户端来连接
const PORT = 3000
app.listen(PORT, () => {
console.log(Express 服务器启动:http://localhost:${PORT})
})
3️⃣ 启动
javascript
nodemon app.js
测试接口:
javascript
curl http://localhost:3000/api/user
疑问解答:
1、express是干什么用的?
Express 是基于 Node.js 的 Web 应用框架,它的核心作用是:帮你更简单、更高效地搭建服务器和处理 HTTP 请求。
2、为什么要用 Express?(对比原生 Node.js)
1️⃣ 原生 Node.js(麻烦)
javascript
const http = require('http')
http.createServer((req, res) => {
if (req.url === '/user' && req.method === 'GET') {
res.writeHead(200, { 'Content-Type': 'application/json' })
res.end(JSON.stringify({ name: '张三' }))
}
}).listen(3000)
❌ 问题:
-
要自己判断
url -
要自己判断
method -
代码臃肿,不好维护
2️⃣ 使用 Express(简单 ✅)
javascript
const express = require('express')
const app = express()
app.get('/user', (req, res) => {
res.json({ name: '张三' })
})
app.listen(3000)
✅ 优点:
-
路由清晰
-
自动解析 JSON
-
代码少一半以上
3、Express 主要干什么用?
| 功能 | 说明 |
|---|---|
| ✅ 路由 | 处理 /login、/user、/order等接口 |
| ✅ 中间件 | 统一处理日志、鉴权、错误处理 |
| ✅ 请求解析 | 自动解析 JSON、表单数据 |
| ✅ 接口返回 | 一行 res.json()搞定 |
| ✅ 生态丰富 | 有 cors、jwt、multer 等插件 |
4、Express 最核心的三个概念
1️⃣ 路由(Route)
javascript
app.get('/', handler)
app.post('/login', handler)
app.put('/user/:id', handler)
根据 URL + 请求方式 处理不同逻辑
2️⃣ 中间件(Middleware)✅ 最重要
javascript
app.use((req, res, next) => {
console.log('有人访问了服务器')
next()
})
中间件 = 请求到达接口前的"关卡"
常见用途:
-
登录校验
-
权限判断
-
打印日志
-
处理异常
3️⃣ 响应方法(Response)
| 方法 | 作用 |
|---|---|
res.send() |
返回任意数据 |
res.json() |
返回 JSON |
res.status() |
设置状态码 |
res.end() |
结束响应 |
五、Node.js 的 fs 文件读写
1、什么是 fs?
fs= File System(文件系统)
👉 用来 读文件 / 写文件 / 改文件名 / 删文件
✅ Node.js 内置模块,不需要安装
2、具体步骤
第一步:引入 fs 模块
javascript
const fs = require('fs')
第二步:准备测试文件
在项目中新建一个文件,如test.txt。
javascript
//test.txt中写
Hello Node.js
我是 fs 模块
第三步:同步 vs 异步(必须先懂)
| 类型 | 特点 |
|---|---|
| 同步 | 阻塞代码(不推荐) |
| 异步 | 非阻塞(✅ 推荐) |
⚠️ Node.js 核心是异步,尽量用异步
文件读取(最重要)
1️⃣ 异步读取(推荐 ✅)
javascript
fs.readFile('test.txt', 'utf8', (err, data) => {
if (err) {
console.log('读取失败:', err)
return
}
console.log('文件内容:', data)
})
✅ 运行:
javascript
node app.js
✅ 输出:
javascript
文件内容: Hello Node.js
我是 fs 模块
2️⃣ 同步读取(了解即可 ❌)
javascript
const data = fs.readFileSync('test.txt', 'utf8')
console.log(data)
文件写入(非常重要)
1️⃣ 覆盖写入
javascript
fs.writeFile('test.txt', '这是新写入的内容', err => {
//如果出错了,就把错误抛出来,让程序停下来并报错
if (err) throw err
console.log('写入成功')
})
特点:
-
文件存在 → 覆盖
-
文件不存在 → 新建
2️⃣ 追加写入(不覆盖)
javascript
fs.appendFile('test.txt', '\n这是追加的内容', err => {
if (err) throw err
console.log('追加成功')
})
判断文件是否存在?
javascript
fs.promises.access('test.txt')
.then(() => console.log('文件存在'))
.catch(() => console.log('文件不存在'))
重命名文件
javascript
fs.rename('test.txt', 'new.txt', err => {
if (err) throw err
console.log('重命名成功')
})
删除文件
javascript
fs.unlink('new.txt', err => {
if (err) throw err
console.log('删除成功')
})
完整示例:
javascript
const fs = require('fs').promises
const handleFile = async () => {
try {
const data = await fs.readFile('test.txt', 'utf8')
console.log('读取成功:', data)
await fs.writeFile('test.txt', 'async/await 写法')
console.log('写入成功')
} catch (err) {
console.log('出错:', err)
}
}
handleFile()
六、Node.js 的 path 路径处理
1、什么是 path?
path是 Node.js 的 内置模块,专门用来 处理文件和目录路径。
2、为什么需要它?
不同操作系统路径分隔符不同
Windows:C:\Users\Admin\file.txt
Linux / Mac:/home/admin/file.txt
手写路径容易出错,拼接路径很麻烦,👉 path 帮你统一解决这些问题
3、具体步骤
第一步:引入 path 模块
javascript
const path = require('path')
拼接路径 : path.join()(✅ 必会)
javascript
const fullPath = path.join('public', 'images', 'logo.png')
console.log(fullPath)
//不同系统输出:
//Windows public\images\logo.png
//Linux / Mac public/images/logo.png
//自动适配系统,不会写死分隔符
解析绝对路径 :path.resolve()
javascript
const absolutePath = path.resolve('uploads', 'file.png')
console.log(absolutePath)
//👉 从根目录开始解析路径
//✅ 常用于:
//配置文件
//静态资源根目录
获取文件名 :path.basename()
javascript
const file = '/user/local/app.js'
console.log(path.basename(file)) // app.js
console.log(path.basename(file, '.js')) // app
获取目录名 :path.dirname()(✅ 必会)
javascript
const file = '/user/local/app.js'
console.log(path.dirname(file)) // /user/local
获取文件后缀 :path.extname()(会用)
javascript
const file = 'image.png'
console.log(path.extname(file)) // .png
解析路径对象 :path.parse()(了解)
javascript
const file = '/user/local/app.js'
console.log(path.parse(file))
//输出:
//{
// root: '/',
// dir: '/user/local',
// base: 'app.js',
// ext: '.js',
// name: 'app'
//}
前端转全栈必须记住的 3 个组合
1️⃣ 读取当前目录文件
javascript
path.join(__dirname, 'config.json')
2️⃣ 静态资源路径(Express)
javascript
path.join(__dirname, 'public')
3️⃣ 文件上传保存路径
javascript
path.join(__dirname, 'uploads', Date.now() + '.png')
七、Node.js 的 url 解析
1、什么是 url 模块?
url是 Node.js 的 内置模块,用来 解析和处理 URL 地址。
2、为什么需要它?
从请求地址中拿到路径
获取 GET 参数
拼接 URL
避免手动字符串切割
3、具体步骤
第一步:引入 url 模块
javascript
const url = require('url')
第二步:核心方法:url.parse()
作用:它可以把一个 URL 字符串,解析成一个对象。
javascript
const url = require('url')
const reqUrl = 'http://localhost:3000/getinfo?id=1&name=tom'
const parsedUrl = url.parse(reqUrl, true) //第二个参数 true的作用:将字符串转化为对象
console.log(parsedUrl)
//解析后的对象结构如下:
//{
// protocol: 'http:',
// host: 'localhost:3000',
// hostname: 'localhost',
// port: '3000',
// pathname: '/getinfo', //请求路径
// query: { id: '1', name: 'tom' }, //GET 参数
// search: '?id=1&name=tom' //URL 中的查询字符串
//}
八、Node.js 的 events 事件驱动
1、什么是 events 模块?
events = Node.js 的事件总线,所有异步操作都靠它通知完成。
2、具体步骤
第一步:引入 events 模块
javascript
const EventEmitter = require('events')
第二步:创建事件发射器(核心)
javascript
const EventEmitter = require('events')
// 创建事件发射器
const emitter = new EventEmitter()
//👉 emitter = 事件中心
第三步:监听事件(订阅)
javascript
emitter.on('sayHi', () => {
console.log('你好,Node.js')
})
第四步:触发事件(发布)
javascript
emitter.emit('sayHi')
注:
1、带参数的事件(非常重要)
javascript
emitter.on('login', (username, time) => {
console.log(`${username} 登录成功,时间:${time}`)
})
emitter.emit('login', 'admin', '2026-01-21')
2、只执行一次的事件(once)
javascript
emitter.once('init', () => {
console.log('只执行一次')
})
emitter.emit('init')
emitter.emit('init')
3、移除事件监听(off)
javascript
const handler = () => {
console.log('事件触发')
}
emitter.on('test', handler)
emitter.emit('test')
emitter.off('test', handler)
emitter.emit('test') // 无输出
九、Node.js 的 stream 大文件处理
1、什么是 stream?
stream是 Node.js 的 内置模块,用来 处理流式数据。
2、具体步骤
第一步:引入模块
javascript
const fs = require('fs')
第二步:可读流(Readable)
javascript
const readStream = fs.createReadStream('big.txt', 'utf8')
readStream.on('data', chunk => {
console.log('收到一块数据:', chunk.length)
})
readStream.on('end', () => {
console.log('读取完成')
})
第三步:可写流(Writable)
javascript
const writeStream = fs.createWriteStream('copy.txt')
writeStream.write('Hello\n')
writeStream.write('Node.js\n')
writeStream.end()
第四步:管道(pipe)------ 核心中的核心
javascript
//文件拷贝(最常用)
const readStream = fs.createReadStream('big.txt')
const writeStream = fs.createWriteStream('copy.txt')
readStream.pipe(writeStream)
十、后端框架 Express 的学习
Express = Node.js 的"语法糖",让你用最少代码写最稳的后端接口。
1、Express 核心(必须精通)
| 知识点 | 为什么重要 |
|---|---|
| **中间件(Middleware)** | ✅ Express 的灵魂 |
| **路由(Router)** | ✅ 接口组织方式 |
| **请求对象(req)** | ✅ 获取参数 |
| **响应对象(res)** | ✅ 返回数据 |
| 错误处理 | ✅ 防止服务器崩溃 |
2、具体步骤
第一步:如何使用Express搭建服务器?
javascript
const express = require('express')
const app = express()
app.get('/', (req, res) => {
res.send('你好 Express')
})
app.listen(3000, () => {
console.log('服务器启动:http://localhost:3000')
})
第二步:中间件(最重要 ⭐⭐⭐⭐⭐)
1️⃣ 什么是中间件?
中间件 = 请求到达接口前的"拦截器"
javascript
app.use((req, res, next) => {
console.log('有人访问了服务器')
next() // 放行
})
2️⃣ 内置中间件(必会)
javascript
// 解析 JSON
app.use(express.json())
// 解析表单
app.use(express.urlencoded({ extended: true }))
// 静态资源
app.use(express.static('public'))
第三步:路由(Router)
1️⃣ 基础路由
javascript
app.get('/users', (req, res) => {})
app.post('/login', (req, res) => {})
2️⃣ 路由模块化(推荐)
javascript
// routes/user.js
const router = express.Router()
router.get('/', (req, res) => {
res.send('用户列表')
})
module.exports = router
javascript
// app.js
const userRouter = require('./routes/user')
app.use('/users', userRouter)
第四步:请求参数(req.xxx)
| 来源 | 写法 |
|---|---|
| URL 参数 | req.params.id |
| Query | req.query.name |
| Body | req.body |
| Header | req.headers |
javascript
app.get('/user/:id', (req, res) => {
res.json({
id: req.params.id,
name: req.query.name
})
})
第五步:响应方法(res.xxx)
| 方法 | 作用 |
|---|---|
res.send() |
返回任意数据 |
res.json() |
返回 JSON |
res.status() |
设置状态码 |
res.end() |
结束响应 |
第六步:文件上传(替代原生 stream)
1️⃣ 安装 multer
javascript
npm install multer
2️⃣ 上传代码(超简单)
javascript
const multer = require('multer')
const upload = multer({ dest: 'uploads/' })
app.post('/upload', upload.single('file'), (req, res) => {
res.send('上传成功')
})
第七步:静态资源服务器(一行搞定)
javascript
app.use(express.static('dist'))
第八步:错误处理(统一兜底)
javascript
app.use((err, req, res, next) => {
console.error(err.stack)
res.status(500).send('服务器出错了')
})
第九步:Express 必装依赖清单
javascript
npm install express
npm install cors # 跨域
npm install morgan # 日志
npm install multer # 上传
npm install dotenv # 环境变量
十一、后端数据库 MongoDB 的学习
| 数据库 | 类型 | 适合前端的原因 | 推荐指数 |
|---|---|---|---|
| MongoDB | 文档型 | 数据结构是 JSON 对象,和 JS 无缝衔接,入门极快。 | ⭐⭐⭐⭐⭐ (首选) |
| MySQL | 关系型 | 最经典、最稳定,几乎所有公司都用,面试必问。 | ⭐⭐⭐⭐⭐ (必学) |
| Redis | 缓存型 | 存 Token、验证码,速度快到飞起。 | ⭐⭐⭐⭐ (进阶) |
1️⃣ 安装驱动
javascript
npm install mongoose
2️⃣ 连接数据库
javascript
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost:27017/myblog');
3️⃣ 定义"模型"(Schema)
javascript
// 定义一个 User 模型
const UserSchema = new mongoose.Schema({
username: String,
password: String,
age: Number
});
const User = mongoose.model('User', UserSchema);
4️⃣ 在接口中进行 CRUD(增删改查)
javascript
// 创建一个用户(Create)
app.post('/user', async (req, res) => {
const user = new User(req.body);
await user.save(); // 保存到数据库
res.send('用户创建成功');
});
// 查询所有用户(Read)
app.get('/users', async (req, res) => {
const users = await User.find(); // 查询数据库
res.json(users);
});
十二、后端数据库 MySQL 的学习
1、MySQL 是什么?(一句话秒懂)
MySQL = 一个专门用来存数据的软件(Excel 表格)
| 前端概念 | MySQL 概念 |
|---|---|
| 项目 | **数据库 (Database)** |
| JS 对象数组 | **表 (Table)** |
| 数组里的对象 | **行 (Row)** |
| 对象的属性 | 列 (Column) |
2、安装 MySQL(最简单方式)
✅ 推荐:Docker(一行命令,不污染电脑)
javascript
docker run --name mysql-db -e MYSQL_ROOT_PASSWORD=123456 -p 3306:3306 -d mysql:8.0
3、Node.js 连接 MySQL(核心代码)
1️⃣ 安装依赖
javascript
npm install mysql2
2️⃣ 创建连接(config.js)
javascript
const mysql = require('mysql2/promise')
// 创建数据库连接池(高性能)
const pool = mysql.createPool({
host: 'localhost',
user: 'root',
password: '123456',
database: 'testdb', // 数据库名
port: 3306
})
module.exports = pool
4、创建表(建 Excel 表头)
javascript
//SQL 语句(必会)
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50),
password VARCHAR(100),
age INT
)
5、Express + MySQL CRUD(增删改查)
1️⃣ 新增用户(Create)
javascript
app.post('/user', async (req, res) => {
const { username, password, age } = req.body
const sql = 'INSERT INTO users (username, password, age) VALUES (?, ?, ?)'
await pool.execute(sql, [username, password, age])
res.send('用户创建成功')
})
2️⃣ 查询用户(Read)
javascript
app.get('/users', async (req, res) => {
const [rows] = await pool.execute('SELECT * FROM users')
res.json(rows)
})
3️⃣ 更新用户(Update)
javascript
app.put('/user/:id', async (req, res) => {
const { username } = req.body
const { id } = req.params
await pool.execute(
'UPDATE users SET username = ? WHERE id = ?',
[username, id]
)
res.send('更新成功')
})
4️⃣ 删除用户(Delete)
javascript
app.delete('/user/:id', async (req, res) => {
const { id } = req.params
await pool.execute('DELETE FROM users WHERE id = ?', [id])
res.send('删除成功')
})
十三、后端数据库 Redis 的学习
1、Redis 是什么?(一句话秒懂)
Redis = 服务器的"超级内存缓存",用来存临时、高频访问的数据。
2、具体步骤
第一步:安装 Redis(最简单方式)
✅ Docker(推荐)
javascript
docker run --name redis-cache -p 6379:6379 -d redis:alpine
第二步:Node.js 连接 Redis
1️⃣ 安装依赖
javascript
npm install ioredis
2️⃣ 创建连接(redis.js)
javascript
const Redis = require('ioredis')
const redis = new Redis({
host: 'localhost',
port: 6379
})
module.exports = redis
第三步:Redis 基本操作(5 分钟上手)
1️⃣ 存数据(SET)
javascript
await redis.set('username', 'admin')
2️⃣ 取数据(GET)
javascript
const username = await redis.get('username')
console.log(username) // admin
3️⃣ 设置过期时间(EXPIRE)
javascript
await redis.set('code', '123456', 'EX', 60) // 60 秒后自动删除
4️⃣ 删除数据(DEL)
javascript
await redis.del('username')
十四、JWT 登录鉴权 + 密码加密(全栈教程)
1、为什么要 JWT + 加密?
| 问题 | 后果 |
|---|---|
| 明文存密码 | 数据库泄露 = 全部账号被盗 |
| 接口无保护 | 任何人都能调用删除接口 |
2、技术分工(先搞清职责)
| 技术 | 作用 |
|---|---|
| bcrypt | ✅ 加密密码(不可逆) |
| JWT | ✅ 生成登录凭证(Token) |
| 中间件 | ✅ 验证 Token 是否有效 |
3、安装依赖
javascript
npm install express mysql2 bcrypt jsonwebtoken cors
4、数据库表结构(users)
javascript
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) UNIQUE,
password VARCHAR(255), -- 存加密后的密码
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)
5、密码加密(bcrypt)
1️⃣ 注册接口(核心代码)
javascript
const bcrypt = require('bcrypt')
app.post('/register', async (req, res) => {
const { username, password } = req.body
// 1. 生成盐(随机字符串)
const saltRounds = 10
const hashedPassword = await bcrypt.hash(password, saltRounds)
// 2. 存入数据库
const sql = 'INSERT INTO users (username, password) VALUES (?, ?)'
await pool.execute(sql, [username, hashedPassword])
res.send('注册成功')
})
//数据库中存的不是明文密码,而是加密串
2️⃣ 密码比对(登录时用)
javascript
const isMatch = await bcrypt.compare(plainPassword, hashedPassword)
6、JWT 生成 Token
1️⃣ 登录接口
javascript
const jwt = require('jsonwebtoken')
app.post('/login', async (req, res) => {
const { username, password } = req.body
// 1. 查用户
const [rows] = await pool.execute(
'SELECT * FROM users WHERE username = ?',
[username]
)
if (rows.length === 0) {
return res.status(400).send('用户不存在')
}
const user = rows[0]
// 2. 验证密码
const isMatch = await bcrypt.compare(password, user.password)
if (!isMatch) {
return res.status(400).send('密码错误')
}
// 3. 生成 JWT
const token = jwt.sign(
{ userId: user.id, username: user.username },
'secret_key', // 密钥(生产环境放环境变量)
{ expiresIn: '1h' }
)
res.json({ token })
})
//前端拿到 Token 后存到 localStorage
7、JWT 验证中间件(重点 ⭐⭐⭐⭐⭐)
1️⃣ 创建鉴权中间件
javascript
const authMiddleware = (req, res, next) => {
const token = req.headers.authorization?.split(' ')[1]
if (!token) {
return res.status(401).send('未登录')
}
try {
const decoded = jwt.verify(token, 'secret_key')
req.user = decoded // 把用户信息挂在 req 上
next()
} catch (err) {
res.status(401).send('Token 无效或过期')
}
}
2️⃣ 保护接口
javascript
// 只有登录用户才能访问
app.get('/profile', authMiddleware, (req, res) => {
res.json({
msg: '这是受保护的接口',
user: req.user
})
})
8、JWT 工作流程(面试必背)
-
用户输入账号密码
-
后端验证密码(bcrypt.compare)
-
验证通过 → 生成 JWT
-
前端保存 Token
-
后续请求携带 Token
-
后端中间件验证 Token
十五、RESTful API + Swagger 教程(前端转全栈版)
1、什么是 RESTful?(一句话秒懂)
RESTful = 用 URL 表示资源,用 HTTP 动词表示方法
2、Express 实现 RESTful 接口
1️⃣ 用户路由(user.js)
javascript
const express = require('express')
const router = express.Router()
// GET /users
router.get('/', (req, res) => {
res.json({ msg: '用户列表' })
})
// GET /users/:id
router.get('/:id', (req, res) => {
res.json({ id: req.params.id })
})
// POST /users
router.post('/', (req, res) => {
res.json({ msg: '创建成功' })
})
// PUT /users/:id
router.put('/:id', (req, res) => {
res.json({ msg: '更新成功' })
})
// DELETE /users/:id
router.delete('/:id', (req, res) => {
res.json({ msg: '删除成功' })
})
module.exports = router
2️⃣ 注册路由(app.js)
javascript
const userRouter = require('./routes/user')
app.use('/users', userRouter)
3、什么是 Swagger?(前端视角)
Swagger = 后端接口的"说明书 + 调试工具"
4、安装 Swagger
javascript
npm install swagger-jsdoc swagger-ui-express
5、配置 Swagger
1️⃣ swagger.js
javascript
const swaggerJsDoc = require('swagger-jsdoc')
const swaggerUi = require('swagger-ui-express')
const options = {
definition: {
openapi: '3.0.0',
info: {
title: '用户管理 API',
version: '1.0.0',
description: 'RESTful API 文档'
}
},
apis: ['./routes/*.js'] // 接口文件路径
}
const swaggerSpec = swaggerJsDoc(options)
module.exports = (app) => {
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerSpec))
}
2️⃣ 启用 Swagger(app.js)
javascript
const setupSwagger = require('./swagger')
setupSwagger(app)
✅ 访问:
javascript
http://localhost:3000/api-docs
6、给接口写 Swagger 注释(重点 ⭐⭐⭐⭐⭐)
✅ 查询用户列表
javascript
/**
* @swagger
* /users:
* get:
* summary: 获取用户列表
* responses:
* 200:
* description: 成功
*/
router.get('/', (req, res) => {})
✅ 创建用户
javascript
/**
* @swagger
* /users:
* post:
* summary: 创建用户
* requestBody:
* required: true
* content:
* application/json:
* schema:
* type: object
* properties:
* username:
* type: string
* password:
* type: string
* responses:
* 200:
* description: 创建成功
*/
router.post('/', (req, res) => {})
✅ 路径参数
javascript
/**
* @swagger
* /users/{id}:
* get:
* summary: 获取用户详情
* parameters:
* - in: path
* name: id
* required: true
* schema:
* type: integer
*/
router.get('/:id', (req, res) => {})
十六、 MVC 架构 + 中间件教程(前端转全栈版)
1、为什么要用 MVC?(痛点)
javascript
app.post('/login', async (req, res) => {
// 1. 校验参数
// 2. 查数据库
// 3. 比对密码
// 4. 生成 Token
// 5. 返回结果
})
👉 问题:
-
一个文件几百行
-
代码无法复用
-
改一处崩一片
2、MVC 是什么?(前端类比)
| 后端 MVC | 前端类比 | 职责 |
|---|---|---|
| Model | API 数据源 | 处理数据(数据库) |
| View | 页面组件 | 返回数据(JSON) |
| Controller | 事件处理函数 | 业务逻辑 |
3、项目目录结构(标准写法)

4、MVC 实战:用户登录
1️⃣ Model(数据层)
javascript
// models/userModel.js
const pool = require('../config/db')
class UserModel {
static async findByUsername(username) {
const [rows] = await pool.execute(
'SELECT * FROM users WHERE username = ?',
[username]
)
return rows[0]
}
}
module.exports = UserModel
2️⃣ Service(业务层)
javascript
// services/userService.js
const UserModel = require('../models/userModel')
const bcrypt = require('bcrypt')
const jwt = require('jsonwebtoken')
class UserService {
static async login(username, password) {
const user = await UserModel.findByUsername(username)
if (!user) {
throw new Error('用户不存在')
}
const isMatch = await bcrypt.compare(password, user.password)
if (!isMatch) {
throw new Error('密码错误')
}
const token = jwt.sign(
{ userId: user.id },
'secret',
{ expiresIn: '1h' }
)
return { token }
}
}
module.exports = UserService
3️⃣ Controller(控制层)
javascript
// controllers/userController.js
const UserService = require('../services/userService')
class UserController {
static async login(req, res) {
try {
const { username, password } = req.body
const result = await UserService.login(username, password)
res.json(result)
} catch (error) {
res.status(400).json({ msg: error.message })
}
}
}
module.exports = UserController
4️⃣ Route(路由层)
javascript
// routes/user.js
const express = require('express')
const router = express.Router()
const UserController = require('../controllers/userController')
router.post('/login', UserController.login)
module.exports = router
5、什么是中间件?(前端拦截器)中间件 = 请求到达接口前的"安检"
javascript
app.use((req, res, next) => {
console.log('有人访问了')
next() // 放行
})
6、JWT 鉴权中间件(实战)
1️⃣ 创建中间件
javascript
// middlewares/auth.js
const jwt = require('jsonwebtoken')
const authMiddleware = (req, res, next) => {
const token = req.headers.authorization?.split(' ')[1]
if (!token) {
return res.status(401).send('未登录')
}
try {
const decoded = jwt.verify(token, 'secret')
req.user = decoded
next()
} catch (err) {
res.status(401).send('Token 无效')
}
}
module.exports = authMiddleware
2️⃣ 使用中间件
javascript
// routes/user.js
const authMiddleware = require('../middlewares/auth')
router.get('/profile', authMiddleware, (req, res) => {
res.json({ user: req.user })
})
7、MVC 请求流程(必背)

十七、Linux + Docker 零基础教程(前端转全栈版)
1、为什么前端要学 Linux & Docker?
| 场景 | 痛点 |
|---|---|
| 本地能跑,服务器报错 | 环境不一致 |
| 依赖冲突 | Node 版本不对 |
| 服务器被黑 | 不懂 Linux 命令 |
| 部署麻烦 | 手动配置太累 |
👉 Docker 解决环境问题,Linux 解决服务器问题
2、Linux 基础(必会 10 个命令)
1️⃣ 进入目录
javascript
cd /home/project
2️⃣ 查看文件
javascript
ls
ll
3️⃣ 创建文件夹
javascript
mkdir project
4️⃣ 编辑文件
javascript
vim app.js
5️⃣ 查看进程
javascript
ps -ef | grep node
6️⃣ 杀死进程
javascript
kill -9 12345
7️⃣ 查看端口
javascript
netstat -tlnp | grep 3000
8️⃣ 下载文件
javascript
wget https://xxx.tar.gz
9️⃣ 解压
javascript
tar -zxvf xxx.tar.gz
🔟 查看日志
javascript
tail -f app.log
3、Docker 是什么?(前端类比)
Docker = 手机里的"虚拟机"
| 前端 | Docker |
|---|---|
| Chrome | 镜像(Image) |
| 打开网页 | 容器(Container) |
| 插件 | Dockerfile |
4、Docker 安装
javascript
curl -fsSL https://get.docker.com | sh
5、Docker 三大核心(必会)
| 概念 | 作用 |
|---|---|
| Image | 模板(安装包) |
| Container | 运行的实例 |
| Dockerfile | 构建脚本 |
6、Docker 常用命令(背下来)
✅ 查看镜像
javascript
docker images
✅ 查看容器
javascript
docker ps
docker ps -a
✅ 启动容器
javascript
docker run -d -p 3000:3000 --name my-app my-image
✅ 停止容器
javascript
docker stop my-app
✅ 删除容器
javascript
docker rm my-app
✅ 查看日志
javascript
docker logs -f my-app
7、Dockerfile(构建 Node.js 项目)
1️⃣ 项目结构

2️⃣ Dockerfile
javascript
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install --production
COPY . .
EXPOSE 3000
CMD ["node", "app.js"]
3️⃣ .dockerignore

4️⃣ 构建镜像
javascript
docker build -t my-node-app .
5️⃣ 运行容器
javascript
docker run -d -p 3000:3000 --name my-app my-node-app
✅ 访问:
javascript
http://服务器IP:3000
8、Docker Compose(一键部署)
✅ docker-compose.yml
javascript
version: '3'
services:
app:
build: .
ports:
- "3000:3000"
depends_on:
- mysql
- redis
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: 123456
volumes:
- mysql-data:/var/lib/mysql
redis:
image: redis:alpine
volumes:
mysql-data:
✅ 启动
javascript
docker-compose up -d
十八、CORS 跨域解决方案(前端转全栈版)
1、什么是 CORS?(一句话秒懂)
CORS = 浏览器的"安全门禁"
2、Express 解决 CORS(3 种方式)
✅ 方式 1:手写中间件(理解原理)
javascript
app.use((req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', '*')
res.setHeader('Access-Control-Allow-Methods', 'GET,POST,PUT,DELETE')
res.setHeader('Access-Control-Allow-Headers', 'Content-Type,Authorization')
next()
})
✅ 方式 2:使用 cors 包(✅ 推荐)
javascript
npm install cors
javascript
const cors = require('cors')
// 允许所有域名
app.use(cors())
// 只允许特定域名
app.use(cors({
origin: 'http://localhost:5173',
credentials: true // 允许携带 Cookie
}))
✅ 方式 3:预检请求(OPTIONS)
javascript
//浏览器在发送 PUT / DELETE / 自定义 Header 时,会先发一个 OPTIONS 请求探路。
app.options('*', cors())
3、前端需要注意的点(重点 ⭐⭐⭐⭐⭐)
1️⃣ 携带 Cookie / Token
javascript
// 前端 Axios
axios.get('/api', {
withCredentials: true, // 必须加
headers: {
Authorization: `Bearer ${token}`
}
})
2️⃣ 后端必须配合
javascript
app.use(cors({
origin: 'http://localhost:5173',
credentials: true // 必须加
}))
4、CORS 常见错误(避坑)
| 错误 | 原因 | 解决 |
|---|---|---|
No 'Access-Control-Allow-Origin' |
后端没配 CORS | 加 cors 中间件 |
Credentials flag is true |
前端带了 Cookie | 后端 credentials: true |
Method not allowed |
预检失败 | 处理 OPTIONS 请求 |
5、开发环境 vs 生产环境
| 环境 | 方案 |
|---|---|
| 开发环境 | ✅ CORS 中间件 |
| 生产环境 | ✅ Nginx 反向代理 |
6、Nginx 反向代理(生产环境推荐)
javascript
location /api/ {
proxy_pass http://backend:3000/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}