nodejs框架 express koa介绍以及从零搭建 koa 模板
express
下载
npm install express
搭建服务
const express = require("express");const app = express();app.get("/home", (req, res) => {res.send("home");
});app.listen(3000, () => {console.log("http://127.0.0.1:3000");
});
restful api
操作 | 请求类型 | url | 返回 |
---|---|---|---|
获取所有 | GET | /users | |
获取单个 | GET | /users/1 | |
新增 | POST | /users | |
修改部分 | PATCH | /users/1 | |
修改全部 | PUT | /users/1 | |
删除 | DELETE | /users/1 |
路由
一个路由由 请求方法 路径 和 回调函数组成
app.get("/users", (req, res) => {res.send("get users");
});app.post("/users", (req, res) => {res.send("post users");
});app.delete("/users", (req, res) => {res.send("delete users");
});app.put("/users", (req, res) => {res.send("put users");
});app.patch("/users", (req, res) => {res.send("patch users");
});
匹配 404 路由
app.all("*", (req, res) => {res.send("404 not found");
});
获取请求报文参数
// /users?a=1&b=2
app.get("/users", (req, res) => {// /usersconsole.log(req.path);// { a: '1', b: '2' }console.log(req.query);// 获取请求头信息console.log(req.get("User-Agent"));
});
获取动态路由参数
app.get("/users/:id", (req, res) => {console.log("id", req.params.id);res.send("get users");
});
获取 post 请求体参数
下载
npm i body-parser
// 引包
const bodyParser = require("body-parser");// 配置
// 解析 querystring 格式请求体
app.use(bodyParser.urlencoded({ extecded: false }));
// 解析 json 格式请求体
app.use(bodyParser.json());app.post("/users", (req, res) => {console.log(req.body);
});
响应
app.get("/users/:id", (req, res) => {// 设置状态码res.status(200);// 设置响应头res.set("abc", "abc");// 返回字符串res.send("get users");// 返回 json 数据res.json({data: "123",});// 重定向res.redirect("http://www.baidu.com");// 下载响应res.download("./test.txt");// 响应文件内容res.sendFile("./test.html");
});
中间件 Middleware
中间件本质是一个回调函数,可以像路由回调一样访问请求对象request
响应对象 response
中间件的作用是:使用函数封装公共操作,简化代码
全局中间件
// 声明中间件
function customMiddleware(req, res, next) {console.log("全局中间件使用了");// 必须调用next();
}// 使用
app.use(customMiddleware);
路由中间件
// 声明中间件
function customMiddleware(req, res, next) {console.log("路由中间件使用了");next();
}// 使用
app.get("/users", customMiddleware, (req, res) => {res.send("get user");
});// 多个中间件使用
app.get("/users", customMiddleware, customMiddleware2, (req, res) => {res.send("get user");
});
静态资源
app.use(express.static(path.join(__dirname, '../public')));// public 文件夹路径可省略不写如下
http://127.0.0.1:3000/mn.png
防盗链 referer
function customMiddleware(req, res, next) {const referer = req.get("referer");next();
}
文件上传 formidable
下载
npm install formidable@v2
使用
const formidable = require("formidable");router.post("/upload", function (req, res, next) {const form = formidable({multiples: true,// 设置上传文件的保存目录uploadDir: path.join(__dirname, "../public/images"),// 保存文件后缀keepExtensions: true,});form.parse(req, (err, fields, files) => {if (err) {next(err);return;}res.json({ fields, files });});
});
koa
下载
npm install koa
使用
const Koa = require("koa");const app = new Koa();app.listen(3000, () => {console.log(`http://127.0.0.1:3000`);
});
获取 get 请求体参数
ctx.request.query
获取动态路由参数
ctx.params?.id
@koa/router 路由
下载
npm install @koa/router
使用
const Router = require("@koa/router");const router = new Router();// 设置路由前缀
// const router = new Router({ prefix: "/users" });router.get("/", (ctx) => {ctx.body = {code: 0,};
});app.use(router.routes());
koa-body
获取 post 请求体参数
下载
npm install koa-body
使用
const { koaBody } = require("koa-body");app.use(koaBody());
获取 post 请求体参数
ctx.request.body
koa-static
配置静态资源
下载
npm install koa-static
使用
const path = require("node:path");
const static = require("koa-static");app.use(static(path.join(__dirname, "../public")));
// http://127.0.0.1:3000/images/test.jpg
npm install koa-views ejs
引入模板文件
下载
npm install koa-views ejs
使用
const views = require("koa-views");
// 此时文件后缀为 .ejs
// app.use(views(path.join(__dirname, "../views"), { extension: "ejs" }));
// 把文件后缀替换为 .html
app.use(views(path.join(__dirname, "../views"), { map: { html: "ejs" } }));router.get("/", async (ctx) => {let title = "你好ejs";let list = ["哈哈", "嘻嘻", "看看", "问问"];let content = "<h2>这是一个h2</h2>";let num = 10;await ctx.render("index", {title,list,content,num,});
});
模板
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><h1>普通模版</h1><h1>ejs循环输出模版</h1><ul><%for(var i=0;i<list.length;i++){%><li><%= list[i] %></li><%}%></ul><h2>原文输出标签</h2><%- content %><h2>条件判断</h2><% if(num> 20){ %>大于20<% }else{ %>小于20<% }%>
</body></html>
formidable 文件上传
下载
npm install formidable@v2
使用
const path = require("node:path");
const formidable = require("formidable");router.post("/", async (ctx, next) => {const form = formidable({multiples: true,// 设置上传文件的保存目录uploadDir: path.join(__dirname, "../public/uploads"),// 保存文件后缀keepExtensions: true,// 修改文件名 必须返回一个字符串即:新的存储文件名称filename: (name, ext, part, form) => {return `ttttt${ext}`;},});await new Promise((resolve, reject) => {form.parse(ctx.req, (err, fields, files) => {if (err) return reject(err);// files.file file就是前端上传的字段名称ctx.body = { fields, files: files.file };resolve();});});return await next();
});
async-validator 数据校验
下载
npm i async-validator
两种模块化使用方式
es6
import Schema from "async-validator";const descriptor = {age: {type: "number",required: true,message: "年龄必填",},
};const validator = new Schema(descriptor);
const values = await validator.validate({ age });
commonjs
const Schema = require("async-validator");const descriptor = {age: {type: "number",required: true,message: "年龄必填",},
};const validator = new Schema.default(descriptor);
const values = await validator.validate({ age });
其他常用校验
const Schema = require("async-validator");async create(ctx) {try{let { name, age, sex } = ctx.request.body;// 参数检验const descriptor = {name: [{// 类型type: "string",// 必填required: true,// 长度(姓名三个字)// len: 3,// 范围(姓名3-5个字)min: 3,max: 5,// 提示信息message: "姓名3-5个字",},{// 自定义校验函数validator: (rule, value) => value.includes("xr"), message: "姓名必须包含xr" },],age: {type: "number",required: true,// 正则pattern: /^[0-9]+$/,// 验证前执行的函数:去除空格transform(value) {return value.trim();},message: "年龄必填",},sex: {type: "enum",enum: [1, 2],required: true,message: "性别错误",},};const validator = new Schema.default(descriptor);const values = await validator.validate({ name, age, sex });}catch(error){const msg = error?.errors[0]?.message;}
}
错误处理 koa-json-error
下载
npm install --save koa-json-error
使用
const error = require("koa-json-error");const app = new Koa();
app.use(error());
cross-env 设置环境变量
下载
npm install --save-dev cross-env
配置变量
package.json
// cross-env NODE_ENV=dev NODE_TEST=true
{"scripts": {"test": "echo \"Error: no test specified\" && exit 1","dev": "cross-env NODE_ENV=dev NODE_TEST=true nodemon ./src/main.js "},
}
获取值
// dev true string
console.log(process.env.NODE_ENV, process.env.NODE_TEST, typeof process.env.NODE_TEST);
dotenv
从 .env 为 nodejs 项目加载环境变量。
下载
npm install dotenv --save
配置使用
在项目的根目录中创建一个 .env 文件
.env
NODE_PORT = 3000;
const path = require("path");
// 添加到 process.env 中,默认获取 .env 文件
require("dotenv").config();// 获取 .env.dev 文件
require("dotenv").config({ path: path.resolve(process.cwd(), ".env.dev") });// 3000
console.log(process.env.NODE_PORT);
jsonwebtoken
下载
npm install jsonwebtoken
生成 token
const jwt = require("jsonwebtoken");
const token = jwt.sign(payload, JWTSECRET, { expiresIn: 60 * 60 * 24 });
验证 token
jwt.verify(token, JWTSECRET);
报错 Expected “payload” to be a plain object.(翻译结果为:“payload”应为纯对象。)
返回的不是纯对象 == res._doc
const res = await UserModel.create(body);
const token = jwt.sign(res._doc, JWTSECRET, { expiresIn: 60 * 60 * 24 });
bcryptjs
下载
npm install bcryptjs
使用
/*** 加密* @param {*} val* @returns*/
const crpytPassword = (val) => {const salt = bcrypt.genSaltSync(10);const hash = bcrypt.hashSync(val, salt);return hash;
};/*** 解密验证* @param {*} val 原始值* @param {*} hash 加密后的值* @returns*/
const checkPassword = (val, hash) => {return bcrypt.compareSync(val, hash);
};
pm2 负载均衡
下载
npm install pm2@latest -g
查看版本
pm2 - v;
启动
pm2 start app.js// --watch 监听
pm2 start app.js --watch// --name 别名
pm2 start app.js --name test
重载(不关闭)和重启(瞬间关闭开启)
pm2 reload app.js
pm2 reload allpm2 restart app.js
pm2 restart all
从 pm2 中关闭
pm2 stop id值// 例
pm2 stop 0
pm2 stop all
从 pm2 中移除
pm2 delete 0
pm2 delete all
查看 pm2 所有项目列表
pm2 list
查看详情
pm2 show name的值// 例
pm2 show app
实时监控查看资源
pm2 monit
查看日志
pm2 logspm2 logs app
mode
-
fork
只启动一个进程单实例,用于多语言混编 python php -
cluster
多实例多进程,只适用 node 一种语言,不需要额外端口配置
生成配置文件
pm2 init simple// 运行
pm2 start .\ecosystem.config.js