node.
1.编写各功能文件并导出,require('相对路径’可无后缀)导入到index.js文件,然后统一导出所有(…│Web 服务器(Node/Express) │。(日志、跨域、解析请求体、cookie、权限校验)先定义普通中间件,再定义路由,最后错误中间件。四、http 模块(创建 Web 服务器)│Web 服务器响应返回│。中间件不写 next() 就卡住不往下走。(匹配 GET/POST +
一、运行环境(前端 vs Node)
- 浏览器环境(前端)
有 JS 引擎(解析执行 JS)
有 Web API:DOM、BOM、Ajax、fetch、Canvas
作用:渲染页面、交互、请求接口
限制:同源策略、跨域限制 - Node.js 环境(后端 / 工程化)
有 JS 引擎
有 内置 API:fs、path、http、stream、crypto
没有 DOM、没有 BOM、没有 window
作用:
写后端接口服务
实现前端工程化(webpack、vite、打包、编译)
运行:集成终端下运行,node 文件名.js
快捷键:⬆⬇切换命令;tab 补全路径;esc清除命令;cls清空终端
二、path 模块
const path = require('path')
// 拼接绝对路径(最常用)
path.join(__dirname, '/a/file.txt', '../')
// ../可覆盖一层
// 获取文件名(带后缀)
path.basename('/root/a/b/c.html') // c.html
// 获取文件名(不带后缀)
path.basename('/root/a/b/c.html', '.html') // c
// 获取后缀名
path.extname('index.html') // .html
// __dirname:当前文件所在文件夹的绝对路径
// __filename:当前文件的绝对路径
三、fs 文件系统模块
const fs = require('fs')
const path = require('path')
const filePath = path.join(__dirname, 'test.txt')
- 写入文件
fs.writeFile(filePath, '内容', (err) => {
// 覆盖式写入
// 只能创建文件,不能创建文件夹
// 路径不存在会报错
})
- 追加写入
fs.appendFile(filePath, '追加内容\n', err => {})
- 读取文件
fs.readFile(filePath, 'utf8', (err, data) => {
if (err) return console.log('读取失败')
console.log(data)
})
//readFile 不写编码默认返回 Buffer 二进制
//写 utf8 才返回字符串
四、http 模块(创建 Web 服务器)
const http = require('http')
const server = http.createServer()
server.on('request', (req, res) => {
//监听客户端请求
// req 请求对象
req.url // 请求地址
req.method // 请求方法 GET/POST
// res 响应对象
//发送中文时,手动设置编码格式
res.setHeader('Content-Type', 'text/html;charset=utf-8')
//向客户端发送内容并结束请求
res.end('响应内容')
// res.end() 只能返回 字符串 / Buffer
//动态响应
if(req.url===''){}
})
///配置端口号,启动服务
server.listen(3000, () => {
console.log('服务器启动:http://localhost:3000')
//终端里ctrl c 终止监听
})
五、模块化(防止变量污染)
类型:
内置模块(导入即可)
自定义模块
第三方模块(包)(需下载)
- CommonJS(Node 默认,.cjs/ 无 type)
//导出
// 方式1
module.exports = { a, b }
// 方式2
exports.a = 1
exports.b = 2
//导入
const m = require('./模块')
//得到永远是module.exports指向的对象,加载模块时会直接执行模块里的代码
//exports 是 module.exports 的引用
//每个模块有个module变量,初始 module.exports={}
//exports===module.exports
// 挂载时对象不变,直接赋值 exports = {} 会断开引用,失效,即换了一个新对象
- ES6 模块化(前端工程化,.mjs/package.json: “type”:“module”)
//默认导出
export default { a, b }
//按需导出
export const a = 1
export function fn(){}
import 变量名 from './模块'
import { a, fn } from './模块'
六、NPM & 包管理
- 初始化
npm init -y
生成 package.json ,记录包的清单,main是导入时包的入口
npm i
根据 package.json 安装所有依赖放入node_modules - 安装包
npm i 包名 // 生产依赖(dependencies)
npm i 包名 -D // 开发依赖(devDependencies)
npm i 包名@版本号 // 指定版本
npm i 包名 -g //全局安装 - 卸载
npm uni 包名
npm uni 包名 -g - nodemon 检测代码变化,自动重启程序
npm i nodemon -g
nodemon 文件名.js //运行 - 镜像源
npm i nrm -g
nrm ls
nrm use taobao // 下载快
nrm use npm // 发布包必须切回官方源
七、常用工具包
moment 格式化时间
const moment = require('moment')
const dt = moment().format('YYYY-MM-DD HH:mm:ss')
八、正则表达式
// 匹配所有字符(包括换行)
const reg = /[\s\S]*/
//压缩
str.replace(/[\r\n]/g,'')
//提取
const r = reg.exec(str) r[0]表示提取出的内容
// \s 空白字符
// \S 非空白字符
// \r 回车
// \n 换行
// g 全局匹配
九、IP & 端口 & 域名
域名和 IP 一一对应
127.0.0.1 = localhost(本机)
端口:标记服务
默认端口:http: 80 https: 443
十、发布包
1.编写各功能文件并导出,require('相对路径’可无后缀)导入到index.js文件,然后统一导出所有(…obj)
2.完善 package.json
name、version、main、description、keyword
3.编写 README.md
4.切换官方镜像
5.终端登录:npm login
6.发布:cd到包的根目录,npm publish
7.删除:npm unpublish 包名 --force
十一、模块加载机制
- 模块加载顺序(优先级从高到低)
- 缓存优先
模块第一次加载后会被缓存,多次 require 只执行一次,拿缓存 - 内置模块
fs/path/http/url 等,直接加载,不用路径 - 第三方模块(node_modules)
找 node_modules/包名/package.json → main 字段
找不到 main → 找 index.js - 自定义模块
必须加路径 ./ …/
没后缀会依次尝试:.js → .json → .node
- 模块加载规则
一次加载,多次缓存
每个模块有独立模块作用域,变量不污染
require() 得到的永远是 module.exports 指向的对象
十二、Express(封装http)
- 服务器
npm i express
//导入
const express = require(‘express’)
//创建
const app = express()
// 监听端口
app.get(‘/api/user’, (req, res) => {
res.send({ name: ‘zs’, age: 20 })
res.send(req.query)// req.query查询参数 ?后的
res.send(req.params)// req.params路径参数 :后的
})
//启动
app.listen(3000, () => {
console.log(‘服务器启动 http://localhost:3000’)
}) - 路由(Router)请求与处理函数映射
创建路由文件 user.js
//导入
const express = require('express')
//创建
const router = express.Router()
//处理
router.get('/list', (req, res) => {
res.send('用户列表')
})
//导出
module.exports = router
注册路由
const userRouter = require('./user.js')
app.use('/api', userRouter) //添加前缀
- 中间件(函数)
作用:预处理请求
语法:(req, res, next) => {next() //转发给下个中间件或路由}
分类:
- 应用级中间件(绑定到app上)
//全局
app.use((req, res, next) => {
console.log('访问了')
next() // 继续向下执行
})
//局部
app.get()
app.post()
- 路由级中间件(绑定到router上)
router.use() - 错误处理中间件
app.use((err, req, res, next)=>{
res.send(‘服务器错误:’ + err.message);
} ) - 内置中间件
//解析 JSON 格式请求体,之后才能用 req.body
app.use(express.json())
//解析表单格式
app.use(express.urlencoded({ extended: false }))
//托管静态资源
app.use(express.static('目录')) //不在url中
app.use('/url',express.static('目录')) //重复调用可托管多个,访问时按顺序查
- 第三方中间件
导入require+注册app.use()
- 跨域cors
分简单请求和预检请求两套机制
简单请求 :浏览器直接发真实请求 → 后端返回允许跨域响应头 → 浏览器校验通过就拿数据。
预检请求:先发一次 OPTIONS 预检请求,询问服务器是否允许跨域、允许的方法和头。预检通过,才发送真实业务请求。
预检请求
方法:PUT / DELETE / PATCH
有自定义请求头(如 token)
Content-Type 为 application/json 等
语法:
npm i cors
const cors = require(‘cors’)
app.use(cors())
组成:
- 浏览器机制
自动检测请求是否跨域,跨域时自动加 Origin 请求头;
非简单请求会自动先发 OPTIONS 预检请求。 - 请求头(浏览器自动携带)
Origin:当前请求来源(协议 + 域名 + 端口) - 响应头(后端必须配置)
Access-Control-Allow-Origin:允许哪些源跨域
Access-Control-Allow-Methods:允许哪些请求方法
Access-Control-Allow-Headers:允许哪些自定义请求头
Access-Control-Allow-Credentials:是否允许携带 Cookie
- session
- 文件上传multer
npm i multer
const multer = require(‘multer’)
const upload = multer({ dest: ‘uploads/’ })
app.post(‘/upload’, upload.single(‘file’), (req, res) => {
res.send(‘上传成功’)
})
顺序
先定义普通中间件,再定义路由,最后错误中间件
先定义的先执行
多个中间件,上游挂载reqh或res对象属性,供下游使用
中间件不写 next() 就卡住不往下走
- 示例
路由模块routes/user.js
//导入创建
const express = require('express');
const router = express.Router();
// 接口
router.get('/list', (req, res) => {
res.send({
status:0, //0表示成功
msg:",
data:req.query
});
});
//导出
module.exports = router;
主文件
//导入创建
const express = require('express');
const app = express();
//中间件
// 引入路由
const userRouter = require('./routes/user');
// 注册路由
app.use('/api/user', userRouter);
//错误处理中间件
//启动
app.listen(3000, () => {
console.log('服务器启动 http://localhost:3000')
})
十三、MySQL
//导入
npm i mysql
const mysql = require('mysql')
//连接
const db = mysql.createPool({
host: 'localhost',
user: 'root',
password: 'root',
database: 'testdb'
})
//导出
module.exports = db
//CRUD
//查
db.query('select * from user', (err, results) => {
if(err) throw err
console.log(results)
})
//条件查询
const sql = 'select * from user where id = ?';
db.query(sql, 1, (err, res)=>{});
//添加:
const sql = 'insert into user(name,age) values(?,?)';
db.query(sql, ['张三', 20], (err, res)=>{});
//修改:
const sql = 'update user set name=? where id=?';
db.query(sql, ['李四', 1], (err, res)=>{});
//删除:
const sql = 'delete from user where id=?';
db.query(sql, 1, (err, res)=>{});//id唯一且不覆盖
//全部用?占位符,占位符为1个时,可省略数组
//查 返回数组,ruselt[0] result.length
//其余返回对象
//标记删除=更新status为1
十四、Web 开发模式(两种)
- 服务端渲染(SSR)
后端拼接 HTML → 返回浏览器
页面在服务器生成,SEO 好,交互少时使用
session认证 - 前后端分离(主流)
前端:Vue/React 渲染页面
后端:只提供 JSON 接口
优点:开发高效、易维护
页面在客户端生成,交互多时使用
JWT 认证
十五、JWT 身份认证
- 作用
替代 Cookie/Session,跨域无压力 - 安装
npm i jsonwebtoken express-jwt - 服务器加密生成 token,浏览器保存到本地
const jwt = require('jsonwebtoken')
const token = jwt.sign(
{ id: 1, username: 'zs' },//信息
'加密秘钥',
{ expiresIn: '24h' }//有效期
)
- 浏览器发送含token请求,服务器还原并验证
const expressJwt = require('express-jwt')
app.use(expressJwt({
secret: '加密秘钥',
algorithms: ['HS256']
}).unless({ path: [/^\/api\/login/] })) //不需权限
- 错误处理
app.use((err, req, res, next) => {
if(err.name === 'UnauthorizedError') {
return res.send({ code: 401, msg: 'token无效' })
//req.auth 获取用户信息
}
})
十六、Session
服务器生成唯一 sessionId
下发到浏览器 Cookie
下次请求自动带 cookie
服务器根据 id 找到对应会话数据
npm install express-session
//创建
const session = require('express-session');
app.use(session({
secret: 'mykey', // 加密密钥
resave: false,
saveUninitialized: true,
cookie: { maxAge: 1000 * 60 * 30 } // 过期时间
}));
//判断是否正确
//存储信息
req.session.user = req.body;
req.session.islogin=true
//取session
res.send(req.session.user);
//销毁 Session(退出登录)
req.session.destroy();
校验格式joi
npm install joi express-joi-validation
十八、bcryptjs 密码加密
npm install bcryptjs
const bcrypt = require(‘bcryptjs’);
// 加密
const pwd = ‘123456’;
const salt = bcrypt.genSaltSync(10);//随机盐的长度
const hashPwd = bcrypt.hashSync(pwd, salt);
// 存 hashPwd 到数据库
// 验证
const isOk = bcrypt.compareSync(‘123456’, 数据库存的加密密码);
if(isOk){
// 登录成功
}
openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构
更多推荐


所有评论(0)