Nodejs构建web服务器有很多中方式,常见的有两种:express
,http.Server
:
express
:轻量级的Nodejs web服务器,功能完善,支持自定义插件http.Server
:NodeJ内置模块,比express
更轻,但需要自己实现请求的处理
本文介绍NodeJs 内置模块http.Server
创建Web服务器:
目录结构
|_ public # 静态资源目录
|_ images # 图片资源
|_ 1.png
|_ index.html # html 资源
|_ index.js # 服务器
index.js
const { readFile } = require("fs");
const http = require("http");
// 注意,这里需要安装mime@^3版本的,mime@4开始使用的是ES Model,无法通过require引入
const mime = require("mime");
// 创建服务器
const server = http.createServer((req, res) => {
//解析请求地址
const url = new URL("http://localhost" + req.url);
// 获取匹配的路由;因为路由使用的是Server 的EventEmitter 实例注册的路由,
// 所以这里获取所有路由可以通过 server.eventNames()获取所有事件名称的方式,获取路由
// 复杂有业务场景时,可以自己实现路由模块
const routeInfo = server.eventNames().find((name) => name == url.pathname);
//如果匹配到路由,则触发对应的路由事件,反之全部按照静态文件处理
if (routeInfo) {
server.emit(`${url.pathname}`, req, res, url);
} else {
// 触发静态资源路由事件
server.emit(`route:public`, req, res, url);
}
});
// 监听8080端口,也可以通过传入0 获取随机端口,并通过,server.address()获取端口信息
server.listen("8080", () => {
console.log("Servre Running",server.address());
});
/**
* 静态资源
*/
server.on("route:public", (req, res, url) => {
//格式化文件路径,如果路径结尾以 "/"结束,则加上index.html
const filepath = url.pathname.endsWith("/")
? url.pathname + "index.html"
: url.pathname;
// 读取public文件夹下匹配的文件
readFile(`./public${filepath}`, (error, data) => {
//如果读取文件失败,则返回404
if (error) {
res.writeHead(404);
res.end("");
} else {
//读取成功,返回200、文件MIME类型,这里使用的是mime插件
res.writeHead(200, {
"Content-Type": mime.getType(filepath),
});
// 返回文件流
res.end(data);
}
});
});
/**
* 普通请求
*/
server.on("/normal", (req, res, url) => {
const id = url.searchParams.get("_id");
res.writeHead(200, {
"Content-Type": "application/json",
});
res.end(JSON.stringify({ id }));
});
/**
* SSE 请求
*/
server.on("/sse", (req, res) => {
// 先向客户端响应SSE响应头信息,让客户端知道接口是一个SSE接口,不要关闭连接
res.writeHead(200, {
"Access-Control-Allow-Origin": "*",
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache",
Connection: "keep-alive",
});
// 每隔3秒发送一个数据
setInterval(() => {
res.write("data:This is SSE API\n\n");
}, 3000);
});
index.html
<!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>
<img src="./images/1.png" alt="" srcset="" />
<script>
fetch("/normal?_id=1111")
.then((res) => res.json())
.then((res) => {
console.log("---client", res);
});
// 请求,并监听sse接口
var evtSource = new EventSource("/sse");
evtSource.onmessage = function (e) {
console.log("---sse", e.data);
};
</script>
</body>
</html>
注意:
- 如果不是最求很高的性能需求,推荐使用完善的
express
创建服务器, http.Server
适合对NodeJs 进阶练习使用,可以开发者知道一个请求从入站到出站的整个流程