如何在Node.js中创建简单的Express类Web服务器
使用Node.js内置库创建自己的Express类Web服务器(第一部分)
学习你选择的语言的最好方法是只用其标准库重新创建他们自己的外部库,这样我们就能更好地理解该语言。在本文中,我将重新创建JavaScript Web服务器库express-js,但有一些差异,并且比真实的Express.js更简单的版本,我将其命名为express-like,如果你想自己制作express-like,可以跟着学习。
第一步:项目初始化
首先创建一个名为express的新目录或文件夹,并执行命令pnpm init来初始化项目,你可以使用你喜欢的包管理器,我在此项目中选择pnpm。
- mkdir express-like && cd express-like
- pnpm init
这会创建名为package.json的文件,修改它使其看起来像这样:
- {
- "name": "express-like",
- "version": "0.0.0",
- "description": "",
- "type": "module",
- "main": "main.js",
- "scripts": {
- "start": "node ."
- },
- "keywords": [],
- "author": "arya dewangga puja",
- "license": "ISC",
- "packageManager": "pnpm@10.9.0"
- }
第二步:创建基础文件
之后让我们跳转到main.js和express-like.js文件。
- import {Express} from "./express-like.js"
- // --> main.js (创建新文件)
- class Express {
- constructor() {
- this.routes = {}
- }
- }
- export {Express}
- // --> express-like.js (创建新文件)
第三步:理解路由存储
首先我们创建一个名为Express的类,在其中我们初始化一些属性,但现在我们只需要一个属性routes,routes是存储所有内容的地方,比如app.get(route, handler)、app.post("path",function)等函数调用存储方法、路径和处理程序在对象中。对象看起来像这样:
- "/path": {
- method: "GET",
- handler: functionCallback
- }
第四步:创建应用实例
- import {Express} from "./express-like.js"
- const app = new Express()
- app.listen()
- // --> main.js (创建新应用)
第五步:添加HTTP服务器功能
- import http from "node:http"
- class Express {
- constructor() {
- // --> express-like.js (在文件顶部导入http)
- class Express {
- // ... 现有代码 ...
- listen(port = 8080) {
- http.createServer((request, response) => {
- response.write("
Hello World
") - response.end()
- })
- .listen(port)
- console.log(`server listen on port ${port}`)
- }
- }
- // --> express-like.js (在构造函数后添加listen方法)
我们创建了一个listen方法,并从node:http内置模块调用http.createServer,以及从http.createServer调用.listen方法。之后尝试用pnpm start运行,它应该能工作。
第六步:添加GET方法
- class Express {
- // ... 现有代码 ...
- get(path, handler) {
- this.routes[path] = {
- method: "GET",
- handler: handler
- }
- }
- // ... 现有代码 ...
- }
- // --> express-like.js (在构造函数后添加get方法)
在get方法中,我们用对象设置路径,对象具有来自参数的method和handler属性,我们将method设置为GET,因为这是一个GET方法。
第七步:创建请求和响应类
- }
- }
- class Express_Request {}
- class Express_Response {}
- export {Express}
- // --> express-like.js (在Express类后创建名为Express_Request和Express_Response的新类)
让我们为我们的处理程序参数创建request和response类。
- class Express_Request {}
- class Express_Response {
- constructor(http_builtinResponse) {
- this._response = http_builtinResponse
- }
- }
- export {Express}
- // --> express-like.js (在Express_Response中添加构造函数)
我们将首先处理response,它有点像来自http.createServer的实际http.ServerResponse的包装器,有了它我们可以制作一些好的方法,比如.json来发送json类型,让我们构建它。
第八步:添加JSON响应方法
- class Express_Response {
- // ... 现有代码 ...
- json(object, status = 200) {
- this._response.writeHead(status, {
- "Content-Type": "application/json",
- "Content-Length": JSON.stringify(object).length
- })
- this._response.write(JSON.stringify(object))
- this._response.end()
- }
- }
- // --> express-like.js (在response类中添加json方法,在构造函数后添加)
这将简化我们处理json类型响应的工作,首先我们添加2个头部,content type和content length,这两个告诉浏览器甚至其他应用程序响应的类型和长度。
第九步:更新监听方法
- class Express {
- // ... 现有代码 ...
- listen(port = 8080) {
- http.createServer((request, response) => {
- const path = request.url
- if (this.routes[path]) {
- this.routes[path].handler(new Express_Request(), new Express_Response(response))
- } else {
- new Express_Response(response).json({ERROR: "404 NOT FOUND"}, 404)
- }
- response.end()
- })
- .listen(port)
- console.log(`server listen on port ${port}`)
- }
- }
- // --> express-like.js (在Express类中更改listen方法)
让我们稍微改变Express类中的listen方法,这里在http.createServer的回调中,我们首先从request.url获取路径,是的我知道,但我喜欢称它为path而不是url,之后我们检查路径是否在this.routes中,如果是,调用该路径的处理程序,如果不是,发送一个json,告诉Error 404 NOT FOUND,让我们试试,但首先让我们为路径/和路径/hello制作一些处理程序。
第十步:添加路由处理程序
- import {Express} from "./express-like.js"
- const app = new Express()
- app.get("/", (request, response) => {
- response.json({messsage: "Welcome to express-like"})
- })
- app.get("/hello", (request, response) => {
- response.json({messsage: "Hello World!"})
- })
- app.listen()
- // --> main.js (添加处理程序)
测试结果
它工作了!现在Express-like只检查路径,不检查像.post、.delete等方法,但我们将在下一章构建它。下一章见(抱歉我的英语不好)。去探索并制作你自己的.post等,如何检查方法类型,自由发挥吧!
完整代码总结
express-like.js
- import http from "node:http"
- class Express {
- constructor() {
- this.routes = {}
- }
- get(path, handler) {
- this.routes[path] = {
- method: "GET",
- handler: handler
- }
- }
- listen(port = 8080) {
- http.createServer((request, response) => {
- const path = request.url
- if (this.routes[path]) {
- this.routes[path].handler(new Express_Request(), new Express_Response(response))
- } else {
- new Express_Response(response).json({ERROR: "404 NOT FOUND"}, 404)
- }
- response.end()
- })
- .listen(port)
- console.log(`server listen on port ${port}`)
- }
- }
- class Express_Request {}
- class Express_Response {
- constructor(http_builtinResponse) {
- this._response = http_builtinResponse
- }
- json(object, status = 200) {
- this._response.writeHead(status, {
- "Content-Type": "application/json",
- "Content-Length": JSON.stringify(object).length
- })
- this._response.write(JSON.stringify(object))
- this._response.end()
- }
- }
- export {Express}
main.js
- import {Express} from "./express-like.js"
- const app = new Express()
- app.get("/", (request, response) => {
- response.json({messsage: "Welcome to express-like"})
- })
- app.get("/hello", (request, response) => {
- response.json({messsage: "Hello World!"})
- })
- app.listen()
学习要点
理解Web服务器基础:通过重新创建Express.js,深入理解Web服务器的工作原理
Node.js内置模块:学习使用node:http模块创建HTTP服务器
路由系统:理解路由如何存储和处理请求
请求/响应对象:创建自定义的Request和Response类
JSON响应:实现JSON格式的响应处理
扩展练习
尝试添加以下功能:
POST、PUT、DELETE等HTTP方法
中间件支持
静态文件服务
错误处理中间件
路由参数支持
关键词:Web开发、编程、教程、Node.js、Express、Web服务器、JavaScript
