创建 Node.js 服务器的初学者指南

2025-05-25

创建 Node.js 服务器的初学者指南

作为全栈开发者,我们使用多种编程语言来构建应用程序的前端和后端。我经常在前端和后端之间来回切换,发现自己会混合使用 JavaScript 和 Ruby 的语法。

程序员要做什么才能保证一切顺利?!

Node.js 解决了这个痛点。它允许 JavaScript 开发人员编写客户端和服务器端代码,而无需学习完全不同的语言。

但是 Node.js 到底是什么?当你查找 Node.js 时,你会看到它被定义为基于 Chrome 的 V8 JavaScript 引擎构建的 JavaScript 运行时(定义来自Node.js)。

替代文本图像

如果你只从定义上认识了 JavaScript、Chrome 和引擎这几个词,却仍然无法理解 Node.js 是什么,那么你并不孤单。我曾经也遇到过同样的问题,觉得是时候了解一下 Node.js 到底是什么了。

那么让我们开始吧!

阅读完本博客后,您将能够:

  1. 用你自己的话定义 Node.js
  2. 学习足够的基础知识来创建 Node.js 服务器并创建处理不同 http 请求的路由。

什么是 Node.js?

Node.js 是一个免费、开源、跨平台的 JavaScript 运行时环境,允许开发人员在浏览器之外编写命令行工具和服务器端脚本(摘自Node.js)。

如果这个定义还不明白,别担心。这些概念将在后续章节中详细解释。

Node.js 的历史

JavaScript 是一种编程语言,最初开发时只在浏览器中运行。它可以操作 DOM 并为您的网站增添交互性。

JavaScript 由 JavaScript 引擎执行。基本上,JavaScript 引擎会将 JavaScript 代码编译成计算机能够更高效运行的机器码。市面上有多种 JavaScript 引擎可供选择。然而,Node.js 选择了 Google 开发的 V8 引擎来运行 JavaScript。

随着 JavaScript 的日益普及,各大浏览器竞相为用户提供最佳性能。越来越多的开发团队致力于为 JavaScript 提供更好的支持,并寻找提高 JavaScript 运行速度的方法。当时,Node.js 基于 V8 JavaScript 引擎构建(摘自Node.js),并因以下原因在开发者中广受欢迎。

Node.js 的定义特征

特性#1 使用 Node.js,您可以使用 JavaScript 编写服务器端代码

与 JavaScript 类似,Node.js 也运行在 V8 JavaScript 引擎上。Node.js 的创建者基于 V8 代码库,并添加了多项功能。这些功能使 Node.js 用户能够使用 JavaScript 构建服务器。

使用 Node.js,您现在可以构建一个连接到数据库的服务器来获取和存储数据、验证用户、验证输入并处理业务逻辑。

特性 #2 Node.js 不局限于服务器。你可以使用 Node.js 编写实用脚本,也可以用它来构建工具。

虽然 Node.js 最常用于 Web 开发和服务器端代码,但你也可以用它做更多的事情!因为 Node.js 是一个 JavaScript 运行时,所以你可以用 Node.js 执行任何 JavaScript 代码。

例如,Node.js 能够访问文件系统,从而读取、写入和操作文件。此功能允许您使用 Node.js 处理计算机上的大量实用任务,而无需将文件公开。

特性 #3 Node.js 使用事件驱动代码来运行逻辑。因此,JavaScript 线程始终可以自由地处理新事件和新传入的请求。

Node.js 包含大量异步代码,这意味着它会注册回调和事件,以便将来执行,而不是立即执行。正是这一特性使得 Node.js 能够以非阻塞方式运行,并让 Node.js 应用拥有极高的性能。

现在我们已经介绍了基本概念,让我们开始动手使用 Node.js 构建服务器吧!

使用 Node.js 创建服务器和路由

这就是我们要建造的!
Node 博客

我们将创建一个非常简单的服务器来处理来自浏览器的请求。

在浏览器端,用户将收到欢迎消息,并被要求通过表单提交他们的心情。

服务器将接收用户输入并创建一个文件来存储用户输入。

我们将在不借助 Express 等框架的情况下完成所有这些任务。这或许是学习 Node.js 的一种更难的方法,但它能帮助我们理解 Node.js 的底层工作原理!

掌握本篇博客中的概念后,请查看我的下一篇博客,了解如何使用 Express 作为框架创建 Node.js 服务器。它会让你更加欣赏 Express,因为它可以用更少的代码行完成我们在本篇博客中要做的大量工作!

先决条件下载在此处
下载 Node.js。保存并运行安装程序。

服务器的代码包含在这个GitHub 仓库中。如果你在操作过程中遇到 bug,可以随时参考它!

步骤 1:为我们的服务器创建一个目录
在适当的目录中,在您的终端中键入以下内容为我们的服务器创建一个目录。

mkdir All_The_Feels
Enter fullscreen mode Exit fullscreen mode

进入 All_The_Feels 目录并在文本编辑器中打开它。

cd All_The_Feels
code .
Enter fullscreen mode Exit fullscreen mode

第 2 步:在 All_The_Feels 目录中创建 server.js 和 routes.js 文件
在您的终端中,执行以下命令。

touch server.js routes.js
Enter fullscreen mode Exit fullscreen mode

您将看到目录中已创建 server.js 和 routes.js 文件。
替代文本

在 server.js 文件中,我们将导入所有必要的组件来设置服务器。服务器将被设置为监听客户端请求。

在 routes.js 文件中,我们将构建路由来处理各种客户端请求并向浏览器发送适当的响应。我们还将在此处编写代码,将用户输入保存到服务器中单独的文件中。

我们首先会关注 server.js。下图提供了 server.js 的最终版本。步骤 3-5 将包含图中指定的相应代码行,以便您轻松跟进!
替代文本

步骤3:在server.js中导入http模块。Node.js
中有多个核心模块。其中,http核心模块可以启动服务器。

要使用 http 模块的功能,我们需要使用 require() 关键字将其导入到 server.js 中。在 server.js 中,创建一个 http 常量并引用 http ,如下所示。

#In server.js(line 1)

const http = require('http')
Enter fullscreen mode Exit fullscreen mode

现在我们可以使用http模块的功能了!

步骤 4:将路由导入 server.js 并创建服务器。http
模块的功能之一是 createServer() 方法。此方法创建一个服务器并接受一个 requestListener 函数,该函数包含两个参数:HTTP 请求 (req) 和响应 (res)。

但是,我们将在这里传递路由,因为我们将在 routes.js 中定义 requestListener。稍后会详细介绍!

通过将服务器声明为常量并将其设置为等于 createServer 方法并将路由作为其参数传递来创建服务器。

#In server.js(line 5)

const server = http.createServer(routes)
Enter fullscreen mode Exit fullscreen mode

为了将路由作为参数传递,我们需要将 routes.js 导入到 server.js 中。为此,请将 routes 声明为常量,并通过提供文件路径来引用 routes。

#In server.js(line 3)

const routes = require("./routes")
Enter fullscreen mode Exit fullscreen mode

最后,我们的服务器需要监听来自浏览器的请求。我们使用 listen() 方法在指定端口创建一个监听器来实现这一点。在 server.listen() 方法中传入 3000 作为参数。

#In server.js(line 7)
server.listen(3000);
Enter fullscreen mode Exit fullscreen mode

现在我们已经配置了 server.js 来创建服务器,接下来让我们关注 routes.js。我们的目标是创建一个 requetListener 函数,它接收客户端请求和服务器响应作为参数。我们将构建路由来处理各种客户端请求,并向浏览器发送相应的响应。

为了避免您在后续操作中出现任何困惑,我们提供了 routes.js 的最终版本。接下来的步骤将逐行讲解代码!

#in routes.js

const fs = require("fs");

const requestListener = (req, res) => {
  const url = req.url;
  const method = req.method;
  if (url === "/") {
    res.write("<html>");
    res.write("<head><title>All the Feels</title></head>");
    res.write(
      '<body><h1>Hey there, welcome to the mood tracker!</h1><p>Enter your mood below and hit send to save your mood.</p><form action = "/mood" method="POST"><input type = "text" name="mood"><button type="submit">Send</button></body>'
    );
    res.write("</html>");
    return res.end();
  }
  if (url === "/mood" && method === "POST") {
    const body = [];
    req.on("data", (chunk) => {
      body.push(chunk);
    });
    return req.on("end", () => {
      const parsedBody = Buffer.concat(body).toString();
      console.log(parsedBody)
      const mood = parsedBody.split("=")[1];
      fs.writeFile("user_mood.txt", mood, () => {});
      return res.end();
    });
  }
};

module.exports = requestListener;
Enter fullscreen mode Exit fullscreen mode

第五步:在 routes.js 中创建一个 requestListener 并导出路由
在 routes.js 中,复制并粘贴以下内容。

# in routes.js

const requestListener = (req, res) => {
  console.log(req)
};
module.exports = requestListener;
Enter fullscreen mode Exit fullscreen mode

让我们来分析一下!

我们将从最后一行代码开始:

module.exports = requestListener;
Enter fullscreen mode Exit fullscreen mode

在步骤#4中,我提到server.js中的createServer()方法接受一个requestListener函数。

#In server.js(line 5)

const server = http.createServer(routes)
Enter fullscreen mode Exit fullscreen mode

但是,由于我们在 routes.js 中定义了 requestListener,因此我们将路由作为参数传递。

我们需要导出路由文件,以便将路由导入到 server.js 中。我们使用 module.exports 关键字来实现。

module.exports = requestListener;
Enter fullscreen mode Exit fullscreen mode

让我们回到代码的顶部!

requestListener 是一个函数,每当服务器收到传入请求时都会执行。此函数接受两个参数:

  1. 请求:传入
  2. 响应:服务器响应
# in routes.js

const requestListener = (req, res) => {
  console.log(req)
};
module.exports = requestListener;
Enter fullscreen mode Exit fullscreen mode

如上代码示例所示,请求和响应分别缩写为 req 和 res。请求和响应都是对象,包含大量有关浏览器发送的请求 (req) 和服务器发送给浏览器的响应 (res) 的信息。

在当前代码中,我在此处添加了 console.log(req) ,以向您展示来自浏览器的典型请求是什么样子。要查看该请求,请在终端中运行以下命令来启动服务器。

#in terminal

node server.js
Enter fullscreen mode Exit fullscreen mode

打开 Chrome 浏览器,在 URL 栏中输入 localhost:3000。目前页面上应该没有任何内容。返回文本编辑器。

在终端中,您将看到一个 req 对象,其中包含大量信息作为键值对。
替代文本

在本教程中,我们将重点关注请求中的键 - url、method 和 headers。要查看这些内容,请将 routes.js 中的代码替换为以下内容。

#in routes.js

const requestListener = (req, res) => {
  console.log(req.url, req.method, req.headers)
};

module.exports = requestListener;
Enter fullscreen mode Exit fullscreen mode

在目前的设置下,每次修改代码后想要查看结果时,都必须手动重启服务器。虽然有一些工具可以帮你完成这项操作,但为了方便本博客,我们将通过按下键盘上的Control + C组合键退出服务器,然后在终端中输入node server.js来重启服务器。

刷新浏览器并返回文本编辑器。

您将在终端中看到以下内容。
替代文本

请求对象中的 URL 以红色框突出显示。“/”表示 localhost:3000 正在发出请求。如果浏览器的 URL 是“localhost:3000/moods”,则请求对象中的 URL 应该显示为“/moods”。

请求的方法以蓝色框突出显示。由于我们没有在浏览器端指定方法,因此它将向服务器发送默认的 GET 请求。

{} 包含标头。它包含有关主机、我们用于该请求的浏览器以及我们将接受的请求类型等信息。

步骤 6:配置“/”路由,用于显示问候语和接受用户输入的表单。
我们的浏览器(localhost:3000)正在向服务器发送 GET 请求,但由于服务器没有返回响应,浏览器没有显示任何内容。由于本教程中我们不会编写前端代码,因此我们将发送一些 HTML 代码作为响应显示在浏览器中。

如果用户从 localhost:3000 的 URL 发送请求,我们将发送一段 HTML 代码,其中包含一条问候语和一个供用户提交心情的表单。我们将用以下代码替换 routes.js 中的代码来实现这一点。

# in routes.js

const requestListener = (req, res) => {
  const url = req.url;
  if (url === "/") {
    res.setHeader("Content-Type", 'text/html')
    res.write("<html>");
    res.write("<head><title>All the Feels</title></head>");
    res.write(
      '<body><h1>Hey there, welcome to the mood tracker!</h1><p>Enter your mood below and hit send to save your mood.</p><form action = "/mood" method="POST"><input type = "text" name="mood"><button type = "submit">Send</button></body>'
    );
    res.write("</html>");
    return res.end();
  }
};
module.exports = requestListener;
Enter fullscreen mode Exit fullscreen mode

让我们逐行检查一下!

由于请求的 url 将决定我们将向客户端发送什么响应,因此我们需要首先从 req 对象中获取 url。

创建一个名为 url 的常量并将其设置为 req 对象中的 url。

# in routes.js

const url = req.url;
Enter fullscreen mode Exit fullscreen mode

如果url的值为“/”(即localhost:3000),我们将发送以下html代码作为响应。

# in routes.js

  if (url === "/") {
    res.setHeader("Content-Type", 'text/html')
    res.write("<html>");
    res.write("<head><title>All the Feels</title></head>");
    res.write(
      '<body><h1>Hey there, welcome to the mood tracker!</h1><p>Enter your mood below and hit submit to save your mood.</p><form action = "/mood" method="POST"><input type = "text" name="mood"><button type = "submit">Send</button></body>'
    );
    res.write("</html>");
    return res.end();
  }
Enter fullscreen mode Exit fullscreen mode

res.setHeader() 方法用于为响应创建标头。标头用于告知浏览器响应对象中的内容类型。由于我们发送的是 HTML 代码,因此我们将 Content-Type 设置为 text/html。

res.write() 方法允许我们将要发送的数据写入响应中。在 Node.js 中,你可以像在前端一样编写 HTML 代码。但是,你必须在每一行开头都使用 res.write 语句,并将 HTML 代码放在括号中,如上所示。

如您所见,我们声明正在编写 html 代码,并将浏览器选项卡的标题设置为“All the Feels”。

body 标签包含多个元素,因此让我们将其分解。

  • h1 标签包含问候信息(嘿,欢迎使用心情追踪器!)
  • p 标签包含用户指示(在下面输入您的心情,然后点击提交以保存您的心情。)
  • form 标签包含 action 和 method 属性。action 属性指定表单提交时表单数据的发送位置。我们指定的位置是 /mood。method 属性指定在表单提交时向服务器发送 POST 请求。
  • 输入标签表明用户输入的类型为文本,输入名称为心情。-button 标签创建一个标记为“发送”的按钮,一旦单击,就会发送请求。

我们写入 res.end() 来表示我们已经完成了在响应中写入数据。

好了!让我们通过退出服务器(control + C)并启动服务器(node server.js)来重新启动服务器。

转到您的浏览器(localhost:3000),您将看到我们的页面上显示的响应!
替代文本

按下键盘上的 Control + Shift + J 打开 DevTools。点击网络选项卡并刷新浏览器。点击名称列下的 localhost(红色箭头)。
替代文本

您将看到我们的 get 请求获得了状态代码 200,这意味着 get 请求成功从服务器获取了适当的数据(绿色框)。

如果您查看响应头(橙色框),您还会看到我们在响应中指定的响应头。 点击“响应”选项卡(红色框)。您将看到我们在服务器中写入的响应内容!
替代文本

到目前为止,我们已经成功创建了 get 请求的路由,并将响应发送到浏览器。下一步是将用户的输入保存到服务器中一个单独的文件中!

第 7 步:将用户输入保存在单独的文件中
在深入研究代码之前,我们需要熟悉 Node.js 如何处理数据,这个概念也称为流。

Node.js 不会等待整个传入数据读入内存,而是逐块读取数据块,处理其内容而不将其全部保存在内存中(摘自NodeSource)。

数据块被进一步分组到缓冲区中。现在,您的代码可以识别这些缓冲区并开始处理数据。

这在处理大量数据(例如流视频)时非常强大,它可以增加应用程序的内存和时间效率!

即使我们的用户输入很少,我们的代码也会反映出 Node.js 如何处理数据。

好的,让我们开始代码吧!

在我们之前编写的 if 语句之后复制并粘贴以下代码。

# in routes.js

 if (url === "/mood" && method === "POST") {
    const body = [];
    req.on("data", (chunk) => {
      body.push(chunk);
    });
    return req.on("end", () => {
      const parsedBody = Buffer.concat(body).toString();
      const mood = parsedBody.split("=")[1];
      fs.writeFile("user_mood.txt", mood, () => {});
      return res.end();
    });
  }
Enter fullscreen mode Exit fullscreen mode

记住我们的表单的 html 代码。

# in routes.js

<form action = "/mood" method="POST"><input type = "text" name="mood">
Enter fullscreen mode Exit fullscreen mode

当用户提交表单时,/mood 的 URL、post 方法以及输入类型(文本)和名称(mood)将被发送到服务器。由于我们仅在表单提交时保存用户输入,因此我们将编写以下 if 语句。

如果传入请求的 url 和方法分别是 /mood 和 post,则将用户输入保存在单独的文件中。

# in routes.js

 if (url === "/mood" && method === "POST") {
        //rest of the code
   }
Enter fullscreen mode Exit fullscreen mode

Node.js 不会等到所有传入消息都读入内存,而是以块的形式处理数据。我们将通过编写一个事件监听器来监听数据,从而实现这一点。

在 Node.js 中,事件监听器由 req.on() 发起。第一个参数指定事件的名称,第二个参数定义事件触发的函数。

在下面的代码中,我们创建一个名为 body 的数组,用于从请求主体中获取数据。然后,我们创建一个事件监听器来监听传入的数据。一旦检测到数据块,它就会将该数据块推送到 body 数组中。

# in routes.js

 const body = [];
    req.on("data", (chunk) => {
      body.push(chunk);
    });
Enter fullscreen mode Exit fullscreen mode

现在我们将创建一个结束监听器。一旦解析完传入的请求数据,结束监听器就会触发。

# in routes.js

 return req.on("end", () => {
      const parsedBody = Buffer.concat(body).toString();
      console.log(parsedBody)
    });
Enter fullscreen mode Exit fullscreen mode

我们之前已将数据块推送到 body 数组中。为了与这些数据块进行交互,我们首先需要将 body 数组中的数据块分组到缓冲区中(Buffer.concat(body))。

现在必须将 Buffer 转换为字符串(.toString()),以便我们的代码可以处理数据!我们将结果设置为 parsedBody。

让我们通过 console.log parsedBody 来查看我们在这里处理什么。

退出并启动服务器,然后刷新浏览器。在表单中输入“Excited”并提交。

你会注意到,浏览器的 URL 会变成 localhost:3000/moods,并显示一个空白页。这是有道理的,因为我们没有为 /moods 这个 URL 编写任何 HTML 代码。

返回服务器终端,您将在终端中看到以下内容。

# in terminal

mood=Excited
Enter fullscreen mode Exit fullscreen mode

这意味着表单正在捕获用户输入,并将其作为请求体发送到服务器。但我们只希望将情绪值“Excited”保存到文件中。

# in routes.js

const mood = parsedBody.split("=")[1];
Enter fullscreen mode Exit fullscreen mode

我们可以通过将 parsedBody(mood=Excited) 拆分为 = 来实现这一点。这将生成一个 ["mood", "Excited"] 数组。我们可以进一步分离“Excited”,方法是指定我们想要的元素位于索引位置 1,并将其保存为 mood 常量。

接下来,我们可以创建一个文件来存储用户输入。在 routes.js 文件的最顶部,我们需要 fs 包并将其设置为 fs 常量。

#In routes.js at the very top of the file

 const fs = require("fs");
Enter fullscreen mode Exit fullscreen mode

在 const mood = parsedBody.split("=")[1] 之后,复制并粘贴以下内容。

fs.writeFile("user_mood.txt", mood, () => {});
      return res.end();
Enter fullscreen mode Exit fullscreen mode

在 route.js 的最顶部,我们导入了 fs 包。该包包含 writeFile 功能,允许我们创建文件并添加任何想要保存的信息。

fs.writeFile 接受两个参数。第一个参数是文件名“user_mood.txt”。第二个参数是要添加到文件的内容。我们将添加一个包含“Excited”值的情绪变量。

最后,我们使用res.end()函数来结束响应过程。

让我们测试一下吧!

停止服务器并启动服务器。打开浏览器,在表单中填写你的心情,然后点击发送。

返回服务器。您将看到服务器中已创建一个名为 user_mood.txt 的文件。进入该文件,您将看到“Excited”已保存在其中!
替代文本

就是这样!这篇博客充满了复杂的概念和代码。非常感谢你坚持读到最后。

替代文本

现在去应用您所学到的知识并添加更多的路线和功能!

文章来源:https://dev.to/lisahjung/beginner-s-guide-to-creating-a-node-js-server-3d0j
PREV
Elasticsearch 初学者指南
NEXT
Vue:计算属性何时可能成为错误的工具