Express详细介绍

142 阅读6分钟

express中间件和路由

路由

  • 路由的目的就是为了区分接口,清除每个接口所需要执行的事情、

  • 当接口相同 时,可以通过自带参数type来区别接口,

  • 两者区别:第一种用于路由区分,这种情况的的优点,可以让路由快速判断,解决问题,通过参数传递,不能直接取到类型,需要解析数据,判断对应的0 是什么?1是什么?

  • 从路由的角度说,直接使用路由区分是最简单的

  • 长连接与短链接的区别:

    • 短链接可以通过路由告诉服务器目的
    • 长连接需要使用属性的type类型来判断
  • 服务端与前端的路由区别

    • 前端路由加#,是哈希路由,哈希的目的是产生历史记录,显示每一个页面
    • 服务端路由为了区分接口。
// package.json
{
  "name": "express1",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "cross-env PORT=4001 nodemon server.js"
  },
  "dependencies": {
    "express": "^4.18.2",
    "cors": "^2.8.5",
    "multer": "1.4.3"
  },
  "devDependencies": {
    "nodemon": "^2.0.22",
    "cross-env": "^7.0.3"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}
// userRouter.js
const express=require('express')
const router=express.Router()
​
router.get('/',function(req,res){
    res.send('aaaa请求成功')
})
router.post('/add',function(req,res){
    console.log(req.body)   
    res.send({err:null,msg:"登录成功"})
})
​
router.post('/logout',function(req,res){
    console.log(req.query)
    res.send({err:null,msg:"退出登录"})
})
​
​
​
module.exports=router
// server.js
const express=require("express");   // 导入express框架
const app=express();       // 创建一个变量名为app
const cors=require("cors");     // 导入express的cors模块
const multer=require("multer")();   // 导入express的multer模块const userRouter=require("./userRouter");
const shoppingRouter=require("./shoppingRouter");
​
app.use(multer.none()); // 处理不需要上传文件的请求
app.use(express.urlencoded({extended:true}))    // 解析编码为 URL 编码的请求体
app.use(express.json());    // 解析 JSON 格式的请求体
app.use(cors());    // 用于启用跨域资源共享// 静态服务器
app.use(express.static("./public"))
// 访问根路径
app.use("/",function(req,res,next){
    res.set("set-Cookie","a=33");
    next();
})
// 访问路由
app.use("/user",userRouter);
app.use("/shopping",shoppingRouter);
​
app.listen(process.env.PORT || 8080);
// 前端
ajax('/user/logout',{user:"张三",password:"13456"})
async function ajax(router,data){
    var res = await fetch("http://localhost:4001"+router,{
        method:"post",
        body:JSON.stringify(data),
        headers:{
            "Content-Type":"application/json"
        }
    })
    var data=await res.json()
    console.log(data)
}

post请求实现过程

  • 前端
        ajax('/user/add',{user:"张三",password:"13456"})
        async function ajax(router,data){
            var res = await fetch("http://localhost:4001"+router,{
                method:"post",
                body:JSON.stringify(data),
                headers:{
                    "Content-Type":"application/json"
                }
            })
            var data=await res.json()
            console.log(data)
        }
  • server
const express=require('express')
const app=express()
const cors=require('cors')
const userRouter=require('./userRouter')
​
app.use(cors())
app.use(express.json()) // 解析前端发过来的数据
​
app.use("/user",userRouter)
​
app.listen(process.env.PORT || 8080)
  • userRouter
const express=require('express')
const router=express.Router()
​
router.get('/',function(req,res){
    res.send('aaaa请求成功')
})
router.post('/add',function(req,res){
    console.log(req.body)   
    res.send({err:null,msg:"登录成功"})
})
​
module.exports=router

路由中间件

  • 通过路由来访问指定的二级路由

内置中间件

  • 静态服务器 :在express中内置中间件仅有一个,就是静态处理,可以快速将静态文件返回给前端
app.use(express.static("./publc"))

错误中间件

  • 错误处理中间件和其他中间件定义类似,只是要使用 4 个参数,而不是 3 个,其签名如下: (err, req, res, next)。
app.use(function(err, req, res, next) {
  console.error(err.stack)
  res.status(500).send('Something broke!')
})

express生成器

  • 下载
npm i express-generator -g
  • 视图创建
express -e
  • 修改package配置
{
  "name": "express1",
  "version": "0.0.0",
  "private": true,
  "scripts": {
    "start": "node ./bin/www"
  },
  "dependencies": {
    "cookie-parser": "~1.4.4",
    "debug": "~2.6.9",
    "ejs": "~2.6.1",
    "express": "~4.16.1",
    "http-errors": "~1.6.3",
    "morgan": "~1.9.1",
    "cors":"^2.8.5",
    "multer":"1.4.3"
  },
  "devDependencies": {
    "nodemon":"^2.0.22",
    "cross-env":"^7.0.3"
  }
}
  • 下载插件
npm i 
// 修改配置
"scripts": {
    "start": "cross-env PORT=4001 nodemon ./bin/www"
  },
  • 启动
npm start

art-template

SSR

  • 直接访问服务器,服务器吐出页面,最大特点:就是直接跳转新页面,卸载当前页面,会产生重新渲染
  • 典型的就是:登录注册,注册成功,等待3s后返回数据
  • SEO的最大作用就是引流

CMS网站发布系统

优化方案

  1. 减少白屏时间:script加载时间过长,这时候使用异步就可以减少,样式的使用也会影响
  2. 提升加载性能:把很多要加载的内容合并在一起,做压缩,比如需要加载10个js,将他合并成1个
  3. 加速减少HTTP请求:使用CDN加载公共库,
  4. 强缓存【服务器】和协商缓存【服务器和客户端】:强缓存就是告诉你这个东西,在规定的时候内不要在向我这边请求,协商缓存就是在请求的时候添加last-modified:是一个时间标识缓存的最后修改时间
  5. 域名收敛:用于移动端。
  6. 域名发散:用于PC端
  7. 并发:用一个时间往服务器请求数据,开启多线程,开启多进程,开启集群;仍然会上线,最高限制。
  8. 怎么解决高并发?添加验证码,域名发散【多个域名访问一个ip地址】。
  9. DNS:域名解析系统,
  10. 使用get请求代替post请求:用get代替post主要目的就是调用缓存
  11. 减少预检请求:
  12. DNS预解析:在head头部中,先进行预解析,跳转到指定域名就是指定的地址,如果跳转页面过多,就是用dns-prefetch
  13. 懒加载:创建一个script。document侦听他,只有用到的时候才调用它。组件的使用也都是懒加载。vue中的路由也是懒加载,
  14. 减少请求内容的体积:开启自动压缩
  15. 优化用户等待体验:白屏使用加载进度条、loading图、骨架屏代替等;

前端art-template

  • 插值
{{ title }}
  • 基本使用

<head>
    <script src="./node_modules/art-template/lib/template-web.js"></script>
</head>
<body>
    <div id="app"></div>

    <script id="tp" type="texe/html">
        <h3>{{value}}</h3>	// 今天星期四
        <p>{{key}}</p>			// 关键知识点呢
        <p>{{day['key']}}</p> // 18
      
        <p>{{a?b:c}}</p>  // 3
        <p>{{a || b}}</p>	// 10
        <p>{{a + b}}</p>	// 13
    </script>

    <script>
        var user={name:"zhangsan",age:30}
        var app=document.querySelector('#app')
        var str=template("tp",{
            value:'今天星期四',
            day:{key:18},
            key:"关键知识点呢",
            a:10,
            b:3,
            c:6
        })
        app.innerHTML=str
        console.log(str)
    </script>
</body>
</html>
  • $data:整个对象
  • 原文输出
<div>{{@ value}}</div>   // 今天星期四
  • list数组渲染
  • 循环对象

art标准语法

  • 基础语法
{{value}}
{{data.key}}
{{data['key']}}
{{a ? b : c}}
{{a || b}}
{{a + b}}
// 答案如上
  • 条件语法
        {{if value}}
            <p>{{value}}</p>
            {{else if key}}
            <span>{{key}}</span>
        {{/if}}
          
// 要是value值不存在将执行key,得到”关键知识点呢“
// 如果存在value值,将执行value,得到”今天星期四“
  • 循环语法
{{each target}}
     {{$index}} {{$value}}// 012345 题
{{/each}}
{{each user $key $val}}
    <div>{{$key}}:{{$val}}</div>
{{/each}}
  
 // user:{key:"zhangsan",val:"18"},
/*
	得到:
    zhangsan:key
    18:val
*/
  • 变量
data:{
    sub:{
        content:"前端学习快乐成长"
    },
    num:{
        s1:"2023-3-31"
    }
}
{{set temp=data.sub.content}}
{{set t=data.num.s1}}
{{temp}}	// 前端学习快乐成长
{{t}}		// 2023-3-31

服务端art-template

  • 添加配置
atr-template
express-art-template
  • 添加解析art
// app.js
var template=require('art-template')
app.set('view engine', 'art');
template.defaults.imports.rendomColor=function(){
  return Array(6).fill(1).reduce((v,t)=>v+(~~(Math.random()*16)).toString(16),'#')
}  // 随机色
  • 使用art替换ejs
<!--layout.art-->
<!doctype html>
<html>
<head>
    <meta charset="utf-8">
    <title>{{block 'title'}}My Site{{/block}}</title>

    {{block 'head'}}
    <link rel="stylesheet" href="main.css">
    {{/block}}
</head>
<body>
    {{block 'content'}}{{/block}}
</body>
</html>
                         

<!--index.art-->
{{extend './layout.art'}}

{{block 'title'}}{{title}}{{/block}}

{{block 'head'}}
    <link rel="stylesheet" href="custom.css">
{{/block}}

{{block 'content'}}
<p>This is just an awesome page.</p>
{{/block}}
  
  
// 服务端
var express=require("express");
var app=express();
app.use(express.static("./"));
app.engine('art', require('express-art-template'));
app.get("/",function(req,res){
   res.render("./index.art",{title:"xietian"});
})
app.listen(4001);
  • 子模板
{{include './header.art'}}
{{include './header.art' data}}
  • 过滤器
var express=require("express");
var template=require("art-template");
var app=express();
app.use(express.static("./"));
app.engine('art', require('express-art-template'));
template.defaults.imports.randomColor=function(){
   var col="#";
   for(var i=0;i<6;i++){
      col+=Math.floor(Math.random()*16).toString(16);
   }
   return col;
}
template.defaults.imports.getSum=function(a,b){
  return a+b;
}
app.get("/",function(req,res){
   res.render("./c.art",{data:"xietian"});
})
app.listen(4001);
{{extend './layout.art'}}
{{block 'title'}}{{data}} site{{/block}}
 {{block 'head'}}
    <link rel="stylesheet" href="./views/b.css">
{{/block}}
{{block 'content'}}

<div style='color:{{randomColor}}'}>asdb</div>
<div>{{getSum(5,6)}}</div>
{{/block}}

CMS

  • 配置package
"dep":{
    expres
}

mongodb

  • 启动
PS C:\WINDOWS\system32> net start MongoDB
MongoDB Server (MongoDB) 服务正在启动 .
MongoDB Server (MongoDB) 服务已经启动成功。
  • package配置
"dep":{
    "cors"
    "art-temp"
    "express-art"
    "mongoose"
}
"dev":{
    "nodemon"
    "cross-env"
}
"start":"wwww"

app.js

var cores=require("cors")
var multer=require("multer"){}
var template=require("art-remplate")

app.set("art",rqeuire("express-art-template"))

socket

  • 后台聊天室
// client.js
const net = require('net')
const readline=require('readline')

var order=readline.Interface({
    input:process.stdin,
    output:process.stdout
})

var socket=new net.Socket()
socket.connect(4001,"10.9.41.101",()=>socket.write("张三"))
socket.on("data",dataHandler)
inputMsg()

function inputMsg(){
    order.question("要发出的消息:",function(msg){
        socket.write(msg)
        inputMsg()
    })
}

function dataHandler(msg){
    console.log("\n"+msg+"")
    inputMsg()
}

// server.js
const net = require('net')
var server = net.createServer()
var list={}
init()
function init(){
    server.on('connection',connectionHandler).listen(4001)
}
function connectionHandler(client){
    client.on("data",msg=>msgHandler(msg,client))
    client.on('error',error=>errorHandler(error,client))
    client.on('close',data=>errorHandler(data,client))
}

function msgHandler(msg,client){
    if(!client.name){
        client.name=msg
        list[client.name]=client
    }else{
        for(var key in list){
            list[key].write(client.name+"说:"+msg+"")
        }
    }
}

function errorHandler(data,client){
    client.end()
}