如何在Node.js中设置Express.js

Express.js 是在使用Node.js构建Web应用程序时最受欢迎的选择。然而,当提到使用 Node.js 构建 Web 应用程序时,通常并不是指在浏览器中看到的内容(除了前端应用程序的服务器端渲染)。相反,Express.js作为 Node.js Web 应用程序框架,使你能够构建 Node.js 中的服务器应用程序。作为后端应用程序,它是你的前端应用程序与潜在数据库或其他数据源(例如 REST APIGraphQL API)之间的连接。只是为了给你一个概念,以下是构建客户端-服务器架构的技术栈列表:

  • React.js(前端)+ Express.js(后端)+ PostgreSQL(数据库)
  • Vue.js(前端)+ Koa.js(后端)+ MongoDB(数据库)
  • Angular.js(前端)+ Hapi.js(后端)+ Neo4j(数据库)

当涉及到前端应用程序时,Express.js 可以与其他后端 Web 应用程序框架交换,就像 React.js 在前端应用程序中与 Vue.js Angular.js 交换一样。Node.js 生态系统并不只提供一种解决方案,而是提供了各种具有其优缺点的解决方案。然而,对于这个应用程序,我们将使用 Express 服务器,因为它是在 Node.js 中构建 JavaScript 后端应用程序时最受欢迎的选择。

开始使用 Express.js Node.js 中进行开发。让我们继续通过在命令行中为之前的 Node.js 应用程序安装 Express.js

1
npm install express

现在,在你的 src/index.js JavaScript 文件中,使用以下代码来导入 Express.js、创建 Express 应用程序的实例并将其启动为 Express 服务器:

1
2
3
4
5
6
7
import express from 'express';

const app = express();

app.listen(3000, () =>
console.log('Example app listening on port 3000!'),
);

一旦你在命令行中使用npm start启动你的应用程序,你应该能够在命令行中看到输出:

1
Example app listening on port 3000!

你的 Express 服务器已经启动并运行。在Express应用程序启动后应该发生的一切都放在回调函数中。该方法本身接受另一个参数作为第一个参数,即运行应用程序的端口。这就是为什么启动后,应用程序可以在浏览器中通过 http://localhost:3000 访问,尽管当你在浏览器中访问时,此 URL 应该还没有可用的内容。

Express.js 中的路由

在后端 Web 应用程序中,路由用于将URI映射到中间件。这些 URI 可以提供文本消息、HTML 页面或通过RESTGraphQL 提供的 JSON 数据。在较大的应用程序中,这意味着有几个路由(中间件),它们映射到几个 URI。在Express中,一个中间件就是一个路由所需的一切,因为路由只是另一个抽象。让我们使用Express设置一个简单的路由:

1
2
3
4
5
6
7
8
9
10
11
import express from 'express';

const app = express();

app.get('/', (req, res) => {
res.send('Hello World!');
});

app.listen(3000, () =>
console.log('Example app listening on port 3000!'),
);

该路由指向你域名的根目录(/)。在浏览器中,你可以通过 http://localhost:3000/ http://localhost:3000(不带尾随斜杠)访问此路由。一旦保存文件,由于我们的设置,应用程序应该会自动重新启动。你可以在命令行中验证它。然后,访问浏览器以查看它为你输出了什么。你应该在那里看到打印的 "Hello World!"。在我们的代码中,我们使用res对象的 send 方法向客户端应用程序发送响应。而 res 对象是我们需要的一切,与指定客户端响应相关,req 对象则是我们从客户端收到的特定请求的一切。这就是 Express.js 中第一个路由的全部内容。我们将在后面学习更多关于路由以及如何与它们交互的知识。

实质上,每个 Express 应用程序都只是一系列路由和中间件函数调用。你之前已经看到了前者,以前是使用单个路由进行路由,为 http://localhost:3000 ``URL / 路由。你可以通过在Express.js中使用路由(例如 /example)来扩展应用程序以添加其他 URI(例如 http://localhost:3000/example

Express.js 中的中间件

如果一个 Express 应用程序由路由和中间件函数调用组成,那么中间件函数调用是什么呢?Express.js 中有两种类型的中间件:应用级中间件和路由级中间件。让我们在本节中探讨应用级中间件,使用一个简洁的用例,并深入了解应用级和路由级中间件的其他方面。

在使用 Express.js 时,当访问 Express 应用程序时,人们经常会在浏览器中遇到以下错误:

1
"Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:3000/. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing)."

这很可能是因为我们正在从一个外部域访问域。跨域资源共享(CORS)是为了在域级别上保护 Web 应用程序而发明的。其思想是:不应该允许从其他域访问数据。例如,具有域 https://example.comWeb 应用程序默认情况下不应该被允许访问具有域 https://website.com 的另一个 Web 应用程序。CORS 用于限制 Web 应用程序之间的访问。

现在,我们可以通过添加丢失的 CORS 头来允许 CORS,因为当我们为 Express 服务器实现一个消费客户端应用程序时,我们最终会遇到此错误。然而,由于我们不想为每个路由手动执行此操作,我们可以使用应用级中间件将 CORS HTTP 头默认添加到每个请求中。因此,我们可以编写一个自定义中间件 – 我们稍后会看到这是如何工作的 – 或者使用一个现成的Express.js中间件库来为我们完成这项工作:

1
npm install cors

接下来,在Express实例的 use 方法中提供它,作为应用程序范围的中间件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import 'dotenv/config';
import cors from 'cors';
import express from 'express';

const app = express();

app.use(cors());

app.get('/', (req, res) => {
res.send('Hello World!');
});

app.listen(3000, () =>
console.log(`Example app listening on port 3000!`),
);

Express 应用程序可以使用来自外部库或自己构建的中间件来扩展其所有路由(应用级中间件)。在这种情况下,所有路由都被扩展为 CORS HTTP 头。现在,默认情况下,所有域都可以访问所有路由。这也包括我们将来消费客户端应用程序的开发域。毕竟,这只是 Express 中间件的一个简单示例。我们将在后面学习更多关于应用级和路由级中间件以及如何编写中间件的知识。

注意:如果你还没有完全理解CORS的目的,不要担心配置 CORS。这是许多初次使用 Express 用户遇到的问题之一,他们通过安装这个好用的库来解决,并且通常不再关心为什么必须安装和使用它。如果你还没有理解,不要担心,但在将你的应用程序部署到生产环境时,你应该设置一个允许访问 Express 服务器应用程序的域的白名单。CORS 库提供了这种配置。花点时间自己去了解一下吧。

Express.js 中的环境变量

在之前,你已经为你的 Node.js 应用程序设置了环境变量。让我们使用一个环境变量来设置你的端口,而不是在源代码中硬编码它。如果没有这样的文件,请在项目中创建一个新的.env文件。否则,使用已经存在的.env文件。给它一个新的键值对来定义你的端口:

1
PORT=3000

现在,在你的 src/index.js 文件中,导入使环境变量在你的源代码中可用的 Node 包,并使用 PORT 环境变量来启动你的Express应用程序:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import 'dotenv/config';
import cors from 'cors';
import express from 'express';

const app = express();

app.use(cors());

app.get('/', (req, res) => {
res.send('Hello World!');
});

app.listen(process.env.PORT, () =>
console.log(`Example app listening on port ${process.env.PORT}!`),
);

现在,你已经将端口存储在一个更敏感的地方,而不是在源代码中公开使用。如果你正在使用类似 GitHubGit,你可以通过将其添加到.gitignore文件中来排除.env文件不上传到 GitHub 仓库中。这样敏感数据就可以远离公共仓库了。如果你最终将你的应用程序部署到生产环境中,你可以将环境变量作为 .env 文件添加到提供应用程序的 Web 服务器上。