发布于 2026-01-06 9 阅读
0

ExpressJS 项目结构

ExpressJS 项目结构

本文最初发表于www.brianemilius.com/expressjs-structure。访问www.brianemilius.com/blog获取更多内容。


ExpressJS 可能是 Node.js 中最流行的服务器端 Web 应用程序开发框架。
在本系列博客中,我将向您展示如何入门以及如何以正确的方式进行开发。

先决条件

  • 具备 Node.js 和 npm 的基础知识
  • 具备一定的 JavaScript 中级知识
  • 基础 HTML 和 CSS

引言

在上一篇博文中,我通过一个非常简单的示例代码向大家介绍了 ExpressJS。

在这篇文章中,我想向你展示如何为你的 ExpressJS 应用程序构建一个合适的项目结构,使其具有可扩展性和健壮性。

我在这里想要做的关键词是“碎片化”。我们将把应用程序拆分成许多小的、模块化的文件。

做出这一选择的理由是:

  • 较小的文件更容易维护。
  • 在GitHub等版本控制平台上,协作进行得更加顺畅。
  • 您可以在不破坏应用程序其他部分功能的情况下,注入或移除其他功能。

文件夹结构

我们先来看一下文件夹结构。

my-express-app/
|   app.js
|   package.json
|
└───node_modules/
|   |   ...
|
└───bin/
|   |   www
|
└───config/
|   |   parsing.js
|   |   view-engine.js
|   |   static-files.js
|   |   database.js
|
└───controllers/
|   |   page.controller.js
|
└───models/
|   |   page.model.js
|
└───views/
|   |   page.ejs
|   |
|   └───partials/
|       |   head.ejs
|       |   seo.ejs
|       |   header.ejs
|       |   footer.ejs
|       |   after-footer.ejs
|
└───routes/
|   |   page.route.js
|   |   router.js
|
assets/
    |   ...
Enter fullscreen mode Exit fullscreen mode

模型、视图、控制器

文件夹modelsviewscontrollers是应用程序功能的核心,旨在采用“MVC”编程设计模式。

配置

config我们将把 Express 使用的所有小型配置文件都放在这个文件夹里。这些文件涵盖了从数据库设置、解析器选择到应用程序视图引擎等各种信息。

路由器

我已将路由逻辑完全从主应用程序文件中分离出来,并单独放在一个文件中。正如我在之前的博文中提到的,我喜欢将应用程序配置和逻辑与路由引擎分开。基本上,路由引擎应该能够独立运行。在我看来,这对于测试来说是一个很好的模式。

www 和 app.js

app.js 文件是应用程序的主文件。它汇集了来自配置和路由的所有线程。此外,该文件还负责处理应用程序错误,并提供错误页面(例如 404 页面)和错误报告(例如日志记录)的流程。

www 文件是应用程序的可执行文件。该文件启动服务器并处理所有与服务器相关的错误。我们可以针对不同的情况使用多个不同的可执行文件。例如,一个可执行文件用于开发环境,另一个用于生产环境。

静态文件

最后,大多数网站都有一堆静态文件需要加载才能在浏览器中查看。这些文件包括样式表、前端相关的 JavaScript 代码、图片和其他媒体文件。这些文件都保存在同一个assets文件夹中。

将碎片连接起来

首先,让我们创建主应用程序文件app.js,代码如下:

// app.js

let express = require("express");
let app = express();

// Here, we will require the configuration files

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

差不多就是这样了。目前是这样。我们还需要添加一些配置文件和路由器的依赖项,但这些以后再说。这些是应用程序运行所需的最基本配置。

接下来我们要创建的文件是bin/www可执行文件。在这个文件中我们需要完成以下三件事:

  • 需要申请
  • 创建服务器实例并使其监听
  • 处理与服务器实例相关的错误
// bin/www

#!/usr/bin/env node
let app = require("../app");
let http = require("http");

// Define a port for the server to listen on
let port = process.env.PORT || 3000;
app.set("port", port);

// Create a server instance
let server = http.createServer(app);

// Make the server listen on a port
server.listen(port);

// Handle errors and success
server.on("error", onError);
server.on("listening", onListening);

function pipeOrPort(address) {
    return typeof address == "string" ? `pipe ${address}` : `port ${address.port}`;
}

function onError(error) {
    if (error.syscall != "listen") {
        throw error;
    }

    let bind = pipeOrPort(server.address());

    switch (error.code) {
        case "EACCES":
            console.error(`${bind} requires elevated privileges.`);
            process.exit(1);
            break;
        case "EADDRINUSE":
            console.error(`${bind} is already in use.`);
            process.exit(1);
            break;
        default:
            throw error;
    }
}

function onListening() {
    let bind = pipeOrPort(server.address());
    console.log(`Listening on ${bind}`);
}
Enter fullscreen mode Exit fullscreen mode

我们首先app从 app.js 中引入模块以及 http 包,它是 Node.js 通用 API 的一部分。

let app = require("../app");
let http = require("http");
Enter fullscreen mode Exit fullscreen mode

接下来,我们定义服务器监听的端口。在本例中,端口号设置为环境变量中指定的值PORT;如果环境变量不存在,则设置为 3000。

let port = process.env.PORT || 3000;
app.set("port", port);
Enter fullscreen mode Exit fullscreen mode

然后我们创建一个服务器实例,并让它监听该端口。

let server = http.createServer(app);
server.listen(port);
Enter fullscreen mode Exit fullscreen mode

文件其余部分是基本的事件处理。我们为两个事件设置了监听器:“error”和“listening”。

server.on("error", onError);
server.on("listening", onListening);
Enter fullscreen mode Exit fullscreen mode

如果触发错误事件,我们会调用onError处理几种不同情况的函数,例如:

  • 服务器无法运行,因为我们指定的端口已被其他程序占用。
  • 服务器无法运行,因为操作系统要求用户拥有某些权限才能运行程序。

如果监听事件被触发,我们会向控制台记录一条简短消息,以告知服务器正在运行。

配置注入

现在应用程序和服务器都已搭建完毕,基本可以运行了,接下来我想向大家展示如何集成配置模块。我们将创建一个配置模块:

  • 静态文件文件夹位置的配置

我们需要两个文件。

// config/static-files.js

module.exports = function(express, app) {
    app.use("/assets", express.static("assets"));
};
Enter fullscreen mode Exit fullscreen mode

express.static("assets")此配置是一个中间件函数。它告诉 Express在对“ http://localhost:3000/assets ”地址的请求中使用一个函数,并将“assets”文件夹作为静态内容提供给客户端。

基本上,这意味着当客户端访问“ http://localhost:3000/assets ”时,他们可以访问“assets”文件夹中的所有内容。

我将在后续文章中更深入地探讨中间件的概念。

最后,将此模块注入到我们的 app.js 文件中。

// app.js

let express = require("express");
let app = express();

// Here, we will require the configuration files
require("./config/static-files")(express, app);

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

把所有东西都测试一遍!

现在是时候检验一下我们所做的一切是否真的有效了。为了测试服务器,我需要在 assets 文件夹中放置一个 HTML 文件,该文件会打印出一条简单的消息,这样我就可以看到到目前为止一切运行正常。

<!-- assets/test.html -->

<h1>Hello there!</h1>
<p>If you can see this, the server is running and has been configured correctly.</p>
Enter fullscreen mode Exit fullscreen mode

现在保存文件,然后使用以下命令从控制台运行服务器。

node bin/www
Enter fullscreen mode Exit fullscreen mode

你应该会看到这条消息。

Listening on port 3000
Enter fullscreen mode Exit fullscreen mode

然后打开浏览器并导航至http://localhost:3000/assets/test.html

你应该看看这个:

浏览器窗口显示演示消息

如果你一直跟着我的讲解,我非常希望得到你的反馈。我演示的概念是否容易理解?或者你希望我解释得更清楚一些?

我在 GitHub 上创建了一个小型代码库,您可以克隆并进行尝试。它包含了本文中提到的所有内容。

下一篇文章将介绍路由器。

本系列文章至今为止的内容

即将发布的文章:

  • ExpressJS 路由器
  • ExpressJS模板引擎
  • ExpressJS 中间件
  • 如何使用 ExpressJS 解析表单内容

建筑照片由 jcomp 拍摄 - www.freepik.com

文章来源:https://dev.to/brianemilius/expressjs-project-struct-2ka4