Skip to content

ExpressJS - 最佳实践

Express.js 应用程序的现代最佳实践

Section titled “Express.js 应用程序的现代最佳实践”

与 Ruby on Rails 等有明确意见的框架不同,Express 在应用程序结构方面为你提供了自由。这种灵活性虽然强大,但随着项目增长,它可能导致维护上的挑战。遵循既定的最佳实践是构建可扩展、可维护和健壮应用程序的关键。

  • 始终以 package.json 开始:使用 npm init -y 初始化每个项目,以管理脚本和依赖项。
  • 使用 .gitignore 文件:立即创建一个 .gitignore 文件,以将 node_modules、.env 文件和其他无关文件排除在版本控制之外。
  • 管理环境变量:绝不要硬编码配置(如数据库凭据、API 密钥或端口)。在本地开发中使用 .env 文件,在生产环境中使用环境变量。dotenv 包是加载这些变量的标准。
  • 使用现代 JavaScript (ESM):采用 ES 模块 (import/export) 以获得更简洁的语法和更好的工具支持。通过在 package.json 中添加 "type": "module" 来启用它。
  • 使用 Linter 和 Formatter:使用 ESLint 和 Prettier 等工具来强制执行一致的代码风格并自动捕获常见错误。这对于团队协作至关重要。
  • 使用 async/await 的异步代码:将所有异步操作标准化为使用 async/await。它比回调或 .then() 链更具可读性且不易出错。将异步路由处理程序包装在 try...catch 块中,并通过 next(error) 将错误传递给集中式处理程序。

清晰组织、职责分离的目录结构至关重要。以下是 REST API 和全栈应用程序中广泛采用且可扩展的结构。

my-app/
├── node_modules/
├── public/ # 静态资源(CSS、图片、客户端 JS)
├── src/ # 主应用程序源代码
│ ├── api/ # 与 API 相关的逻辑,通常会进行版本控制(例如 v1, v2)
│ │ ├── users/ # 基于功能的模块(例如 users, products)
│ │ │ ├── user.controller.js # 处理请求/响应,调用服务
│ │ │ ├── user.model.js # 数据库 Schema/模型(例如 Mongoose, Sequelize)
│ │ │ ├── user.routes.js # 定义此功能的路由
│ │ │ ├── user.service.js # 业务逻辑,数据库交互
│ │ │ └── user.validation.js # 请求验证 Schema(例如 Joi, express-validator)
│ │ └── index.js # 聚合所有 API 路由(例如 router.use('/users', ...))
│ ├── config/ # 配置文件(数据库等)
│ ├── middleware/ # 自定义中间件(认证、日志记录、错误处理)
│ ├── services/ # 共享服务(电子邮件、支付等)
│ ├── utils/ # 工具函数和类
│ └── app.js # Express 应用设置,中间件注册
├── views/ # 服务器端模板(EJS, Pug)
├── .env # 环境变量(请勿提交)
├── .env.example # 供其他开发者参考的环境变量示例文件
├── .gitignore
├── package.json
└── server.js # 入口文件:导入 app.js 并启动服务器
  • 职责分离:每个文件都有单一职责(例如,routes 定义端点,controllers 协调,services 执行业务逻辑)。
  • 模块化:功能被分组到自包含的目录中(users/、products/),使代码库更易于导航和扩展。
  • 可测试性:将逻辑分离到服务和工具中使单元测试更容易,因为你可以在不需要 HTTP 服务器的情况下测试业务逻辑。
  • 服务器与应用程序解耦:app.js 文件设置 Express 应用程序,而 server.js 负责启动 HTTP 服务器。这对于集成测试至关重要,你可以在不启动实时服务器的情况下导入 app 对象。
  • 使用 helmet:一个基本的安全中间件,用于设置重要的 HTTP 头。
  • 实施速率限制:使用 express-rate-limit 防范暴力破解和 DoS 攻击。
  • 数据验证:使用 joi 或 express-validator 等库,对来自用户的所有传入数据(req.body、req.query、req.params)进行清理和验证,以防止注入攻击并确保数据完整性。
  • 使用结构化日志记录器:在生产环境中,使用 pino 或 winston 等日志记录库,而不是 console.log。它们提供分级、结构化(JSON)的日志,更易于解析和分析。
  • 优雅关机:实现逻辑来处理 SIGINT 和 SIGTERM 信号,以便在服务器退出前关闭数据库连接并完成请求处理。

掌握这些最佳实践是一个重要的进步。要进一步提升,可以探索:

  • TypeScript:为你的 Express 应用程序添加静态类型可以显著减少 bug 并提高可维护性。
  • 容器化:学习使用 Docker 将你的 Express 应用程序容器化,以实现一致的开发和部署环境。
  • 高级 API 概念:深入研究 GraphQL 作为 REST 的替代方案,或者探索像 WebSockets 这样的模式来实现实时通信。
  • 基础设施即代码:Terraform 或 Pulumi 等工具可以帮助你通过编程方式管理云部署资源。