nodejs-best-practices

nodejs-best-practices

热门

Node.js 开发原则与决策。框架选择、异步模式、安全性和架构。教授思考方法,而非复制代码。

4.2万Star
6745Fork
更新于 2026/7/1
SKILL.md
readonly只读
name
nodejs-best-practices
description

Node.js 开发原则与决策。框架选择、异步模式、安全性和架构。教授思考方法,而非复制代码。

Node.js 最佳实践

2025 年 Node.js 开发的原则与决策。
学会思考,而非死记硬背代码模式。

何时使用

在进行 Node.js 架构决策、选择框架、设计异步模式或应用安全与部署最佳实践时使用此技能。


⚠️ 如何使用此技能

此技能教授决策原则,而非固定的可复制代码。

  • 当不明确时,询问用户的偏好
  • 根据上下文选择框架/模式
  • 不要每次都默认使用相同的解决方案

1. 框架选择(2025)

决策树

你在构建什么?
│
├── 边缘/无服务器(Cloudflare, Vercel)
│   └── Hono(零依赖,超快冷启动)
│
├── 高性能 API
│   └── Fastify(比 Express 快 2-3 倍)
│
├── 企业/团队熟悉度
│   └── NestJS(结构化,依赖注入,装饰器)
│
├── 遗留/稳定/最大生态系统
│   └── Express(成熟,中间件最多)
│
└── 全栈与前端
    └── Next.js API 路由或 tRPC

比较原则

因素 Hono Fastify Express
最适合 边缘,无服务器 性能 遗留,学习
冷启动 最快 中等
生态系统 增长中 良好 最大
TypeScript 原生 优秀 良好
学习曲线 中等

选择时需问的问题:

  1. 部署目标是什么?
  2. 冷启动时间是否关键?
  3. 团队是否有现有经验?
  4. 是否有遗留代码需要维护?

2. 运行时考虑(2025)

原生 TypeScript

Node.js 22+:--experimental-strip-types
├── 直接运行 .ts 文件
├── 简单项目无需构建步骤
└── 适用于:脚本,简单 API

模块系统决策

ESM(import/export)
├── 现代标准
├── 更好的 tree-shaking
├── 异步模块加载
└── 用于:新项目

CommonJS(require)
├── 遗留兼容性
├── 更多 npm 包支持
└── 用于:现有代码库,某些边缘情况

运行时选择

运行时 最适合
Node.js 通用,最大生态系统
Bun 性能,内置打包器
Deno 安全优先,内置 TypeScript

3. 架构原则

分层结构概念

请求流程:
│
├── 控制器/路由层
│   ├── 处理 HTTP 细节
│   ├── 边界输入验证
│   └── 调用服务层
│
├── 服务层
│   ├── 业务逻辑
│   ├── 框架无关
│   └── 调用仓库层
│
└── 仓库层
    ├── 仅数据访问
    ├── 数据库查询
    └── ORM 交互

为何重要:

  • 可测试性:独立模拟各层
  • 灵活性:更换数据库而不影响业务逻辑
  • 清晰性:每层有单一职责

何时简化:

  • 小型脚本 → 单个文件即可
  • 原型 → 较少结构可接受
  • 始终问:“这会增长吗?”

4. 错误处理原则

集中式错误处理

模式:
├── 创建自定义错误类
├── 从任何层抛出
├── 在顶层捕获(中间件)
└── 格式化一致响应

错误响应理念

客户端获得:
├── 适当的 HTTP 状态码
├── 用于程序化处理的错误码
├── 用户友好的消息
└── 无内部细节(安全!)

日志获得:
├── 完整堆栈跟踪
├── 请求上下文
├── 用户 ID(如适用)
└── 时间戳

状态码选择

情况 状态码 何时使用
错误输入 400 客户端发送无效数据
未认证 401 缺少或无效凭据
无权限 403 有效认证但不允许
未找到 404 资源不存在
冲突 409 重复或状态冲突
验证失败 422 模式有效但业务规则失败
服务器错误 500 我们的错,记录所有信息

5. 异步模式原则

何时使用每种模式

模式 使用场景
async/await 顺序异步操作
Promise.all 并行独立操作
Promise.allSettled 并行操作,部分可能失败
Promise.race 超时或第一个响应胜出

事件循环意识

I/O 密集型(异步有帮助):
├── 数据库查询
├── HTTP 请求
├── 文件系统
└── 网络操作

CPU 密集型(异步无帮助):
├── 加密操作
├── 图像处理
├── 复杂计算
└── → 使用工作线程或卸载

避免阻塞事件循环

  • 生产环境中绝不使用同步方法(如 fs.readFileSync)
  • 卸载 CPU 密集型工作
  • 对大数据使用流式处理

6. 验证原则

在边界处验证

验证位置:
├── API 入口点(请求体/参数)
├── 数据库操作前
├── 外部数据(API 响应,文件上传)
└── 环境变量(启动时)

验证库选择

最适合
Zod TypeScript 优先,类型推断
Valibot 更小的包(可 tree-shake)
ArkType 性能关键
Yup 现有 React 表单使用

验证理念

  • 快速失败:尽早验证
  • 具体明确:清晰的错误消息
  • 不信任:即使是“内部”数据

7. 安全原则

安全检查清单(非代码)

  • [ ] 输入验证:所有输入均已验证
  • [ ] 参数化查询:SQL 不使用字符串拼接
  • [ ] 密码哈希:bcrypt 或 argon2
  • [ ] JWT 验证:始终验证签名和过期时间
  • [ ] 速率限制:防止滥用
  • [ ] 安全头:Helmet.js 或等效
  • [ ] HTTPS:生产环境处处使用
  • [ ] CORS:正确配置
  • [ ] 密钥:仅使用环境变量
  • [ ] 依赖:定期审计

安全思维

不信任任何内容:
├── 查询参数 → 验证
├── 请求体 → 验证
├── 请求头 → 验证
├── Cookie → 验证
├── 文件上传 → 扫描
└── 外部 API → 验证响应

8. 测试原则

测试策略选择

类型 目的 工具
单元测试 业务逻辑 node:test, Vitest
集成测试 API 端点 Supertest
端到端测试 完整流程 Playwright

测试内容(优先级)

  1. 关键路径:认证、支付、核心业务
  2. 边界情况:空输入、边界值
  3. 错误处理:失败时会发生什么?
  4. 不值得测试:框架代码、琐碎的 getter

内置测试运行器(Node.js 22+)

node --test src/**/*.test.ts
├── 无外部依赖
├── 良好的覆盖率报告
└── 支持监视模式

9. 应避免的反模式

❌ 不要:

  • 对新边缘项目使用 Express(使用 Hono)
  • 在生产代码中使用同步方法
  • 将业务逻辑放在控制器中
  • 跳过输入验证
  • 硬编码密钥
  • 不经验证信任外部数据
  • 用 CPU 工作阻塞事件循环

✅ 应该:

  • 根据上下文选择框架
  • 当不明确时询问用户偏好
  • 对增长中的项目使用分层架构
  • 验证所有输入
  • 对环境变量使用密钥
  • 优化前先分析

10. 决策检查清单

在实现之前:

  • [ ] 询问了用户关于技术栈的偏好?
  • [ ] 针对此上下文选择了框架?(而非默认)
  • [ ] 考虑了部署目标?
  • [ ] 规划了错误处理策略?
  • [ ] 确定了验证点?
  • [ ] 考虑了安全需求?

记住:Node.js 最佳实践是关于决策,而非死记硬背模式。每个项目都应根据其需求进行全新考虑。

限制

  • 仅当任务明确符合上述范围时使用此技能。
  • 不要将输出视为环境特定验证、测试或专家审查的替代品。
  • 如果缺少必要的输入、权限、安全边界或成功标准,请停止并请求澄清。