重新实现Express:第1部分

几周前,我决定开始重新实现Express作为辅助项目。 这是我和教学团队之前在Northcoders上进行过简短实验的东西,我认为这是一个有趣的,即使具有挑战性的小项目,因为我有空余时间。

那么什么是Express? 这是用于NodeJS服务器端应用程序开发的轻量级框架。 我定期使用它来构建API和服务应用程序。 它简单易用,并建立在中间件模型上,即在服务器接收到请求之前,请求和响应对象按顺序传递(数组,有人吗?)的功能,直到您决定响应为止。

如果您对JavaScript语言,HTTP的工作方式以及Express本身的工作方式有信心,我认为这是一个完美的项目。 它具有许多小巧且易于识别的功能,这些功能可以很好地相互构建,并且为您提供了解决小而棘手的问题并使用一系列JS语言功能的大量机会。 我已经了解了要实现的功能的2/3方式,并且使用了递归,构造函数,复杂的正则表达式,并熟悉了Node HTTP模块。 因此,如果您认为这听起来很有趣,那么我建议您继续尝试一下-但是,如果您不喜欢它,但想进一步了解Express及其内部功能,请继续阅读!

首先,这是我一开始要实现的功能:

  • 可以获取新的Hexpress应用
  • 自定义响应方法
  • 默认404错误处理
  • 基本的app.get()路由
  • app.put(),app.post(),app.delete(),app.all()路由
  • 支持自定义中间件
  • 支持自定义错误中间件
  • 支持参数化路线
  • 支持查询
  • 支持提供静态文件
  • 使用模板引擎的支持
  • Hexpress路由器

是的,我决定主要将克隆称为“ Hexpress”,这样我就可以在代码中散布诡异的单词和万圣节双关语。 🎃

在本博客系列中,我将介绍实现的功能并共享一些带注释的代码。

那么,从哪里开始呢?

const app = express();

这是从Express开始的第一行。 它会创建一个新的Express应用程序,其中包含您可能熟悉的许多方法,例如app.listen()app.get()app.use()app.listen是您使用端口和可选回调调用的函数:

事实证明,Express的app.listen与Node的Http.Server.listen相同,而app.listen实际上返回Node的HTTP Server的实例,因此Node HTTP模块使这部分出乎意料的简单:

当我们调用hexpress()我们使用一个listen方法返回一个对象。 listen方法只是将您提供给Node.Server的listen方法的任何参数传递。 然后,它返回Node服务器本身,以防万一您需要它。 它可能很方便-它具有诸如closegetConnections

作为一项改进,我们可能无法在每次创建Express应用程序时都创建一个新的侦听方法。 我的意思是……我认为这没什么大不了的,因为在一个项目中实际创建了多少个Express应用程序? 但是无论如何,我们还是要重构它以共享原型上的方法……

而且您可以在此处看到,只要节点服务器收到HTTP请求,它现在也会响应。 它只是现在回显方法和路径。

res.status(200).send(’一切都好!’);

如果您使用过Express,您将知道它提供了响应方法,这些方法可以帮助我们节省执行res.writeres.end以及所有这些res.write的工作的工作。 我们应该将那些方便的方法添加到响应对象上。 同时,我们也可以添加任何其他有趣的响应方法。

res只是一个对象,因此我们可以传递对其的引用,为其添加一些方法,然后将其返回以供将来使用:

那么addResMethods做什么的呢? 好吧,只需将那些方便的方法添加到响应对象即可。 您可以添加很多方法,但是对于初学者来说,我喜欢res.sendFile的外观,可以发送一个文件,还有sendStatus ,它可以设置状态代码,还可以发送适当的文本响应, res.set可以设置您的响应标头,以及可以使用Buffer,字符串,对象或数组并将其发送回用户的良好的老式res.send 。 所有这些方法都提供了对Node Response Object上方法的抽象,一点也不花哨。

请注意, res.status()是可链接的,这意味着我们可以执行res.status(200).send('Foo!')因此, res.status返回this请求对象很重要,这样我们就可以进一步进行链接了方法。

您还将在其中看到几个辅助函数divineContentType ,它采用文件路径(例如“ public / foo / index.html”),并为标头(例如“ text / html”)返回正确的内容类型,而getAppropriateTextResponse如果您不愿意自己设置状态代码,则会使用状态代码并返回一个简单但适当的文本字符串来陪伴它。 例如,状态201给出文本“已创建”,而状态418给出“我是茶壶”。 这些辅助函数只是非常无聊的switch语句。

现在我们正朝着类似于Express的方向发展,但是我们仍然缺少那些关键的app.getapp.putapp.post方法, app.post方法允许我们设置功能以处理特定路线上的请求。

这就是我将在本系列的下一篇博客文章中讨论的内容!

感谢您的阅读,我很想知道您的想法,特别是如果您亲自尝试过该项目! 你将做点什么不同的? 我对Express的工作方式怀念什么? 🦄

您可以在这里看到我已经完成的完整源代码。

在第2部分中,我将讨论如何实现app.get()方法!