nodejs-backend

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Node.js Backend

Node.js后端开发

Framework Selection

框架选择

ContextChooseWhy
Edge/ServerlessHonoZero-dep, fastest cold starts
Performance APIFastify2-3x faster than Express, built-in schema validation
Enterprise/teamNestJSDI, decorators, structured conventions
Legacy/ecosystemExpressMost middleware, widest adoption
Ask user: deployment target, cold start needs, team experience, existing codebase.
场景选择框架原因
边缘计算/无服务器Hono零依赖,冷启动速度最快
高性能APIFastify速度比Express快2-3倍,内置Schema验证
企业级/团队项目NestJS依赖注入、装饰器、结构化规范
遗留项目/生态兼容Express中间件最丰富,普及率最高
询问用户:部署目标、冷启动需求、团队技术经验、现有代码库情况。

Architecture

架构设计

src/
├── routes/          # HTTP: parse request, call service, format response
├── middleware/       # Auth, validation, rate limiting, logging
├── services/        # Business logic (no HTTP types)
├── repositories/    # Data access only (queries, ORM)
├── config/          # Env, DB pool, constants
└── types/           # Shared TypeScript interfaces
  • Routes never contain business logic
  • Services never import Request/Response
  • Repositories never throw HTTP errors
  • For scripts/prototypes: single file is fine — ask "will this grow?"
src/
├── routes/          # HTTP层:解析请求、调用服务、格式化响应
├── middleware/       # 鉴权、验证、请求频率限制、日志
├── services/        # 业务逻辑(无HTTP类型依赖)
├── repositories/    # 仅数据访问(查询、ORM)
├── config/          # 环境变量、数据库连接池、常量
└── types/           # 共享TypeScript接口
  • 路由层绝不包含业务逻辑
  • 服务层绝不导入Request/Response类型
  • 数据访问层绝不抛出HTTP错误
  • 对于脚本/原型项目:单文件实现即可——询问“该项目是否会扩展?”

TypeScript Rules

TypeScript规则

  • Use
    import type { }
    for type-only imports — eliminates runtime overhead
  • Prefer
    interface
    for object shapes (2-5x faster type resolution than intersections)
  • Prefer
    unknown
    over
    any
    — forces explicit narrowing
  • Use
    z.infer<typeof Schema>
    as single source of truth — never duplicate types and schemas
  • Minimize
    as
    assertions — use type guards instead
  • Add explicit return types to exported functions (faster declaration emit)
  • Untyped package?
    declare module 'pkg' { const v: unknown; export default v; }
    in
    types/ambient.d.ts
  • 使用
    import type { }
    进行仅类型导入——消除运行时开销
  • 优先用
    interface
    定义对象结构(类型解析速度比交叉类型快2-5倍)
  • 优先用
    unknown
    而非
    any
    ——强制显式类型收窄
  • 使用
    z.infer<typeof Schema>
    作为唯一数据源——绝不重复定义类型和Schema
  • 尽量减少
    as
    类型断言——改用类型守卫
  • 为导出函数添加显式返回类型(加快声明文件生成速度)
  • 遇到无类型的包?在
    types/ambient.d.ts
    中添加
    declare module 'pkg' { const v: unknown; export default v; }

Validation

验证方案

Zod (TypeScript inference) or TypeBox (Fastify native). Validate at boundaries only: request entry, before DB ops, env vars at startup. Use
.extend()
,
.pick()
,
.omit()
,
.partial()
,
.merge()
for DRY schemas.
Zod(TypeScript类型推导)或TypeBox(Fastify原生支持)。仅在边界处进行验证:请求入口、数据库操作前、启动时验证环境变量。使用
.extend()
.pick()
.omit()
.partial()
.merge()
实现DRY(不重复)的Schema。

Error Handling

错误处理

Custom error hierarchy:
AppError(message, statusCode, isOperational)
ValidationError(400)
,
NotFoundError(404)
,
UnauthorizedError(401)
,
ForbiddenError(403)
,
ConflictError(409)
Centralized handler middleware:
  • AppError
    → return
    { error: message }
    with statusCode
  • Unknown → log full stack, return 500 + generic message in production
  • Async wrapper:
    const asyncHandler = (fn) => (req, res, next) => Promise.resolve(fn(req, res, next)).catch(next);
Codes: 400 bad input | 401 no auth | 403 no permission | 404 missing | 409 conflict | 422 business rule | 429 rate limited | 500 server fault
自定义错误层级:
AppError(message, statusCode, isOperational)
ValidationError(400)
NotFoundError(404)
UnauthorizedError(401)
ForbiddenError(403)
ConflictError(409)
集中式错误处理中间件:
  • AppError
    → 返回
    { error: message }
    及对应状态码
  • 未知错误 → 在生产环境中记录完整堆栈信息,返回500状态码和通用错误信息
  • 异步包装器:
    const asyncHandler = (fn) => (req, res, next) => Promise.resolve(fn(req, res, next)).catch(next);
状态码说明:400(输入错误)| 401(未授权)| 403(无权限)| 404(资源不存在)| 409(资源冲突)| 422(业务规则不满足)| 429(请求频率超限)| 500(服务器故障)

API Design

API设计规范

  • Resources: plural nouns (
    /users
    ), max 2 nesting levels (
    /users/:id/orders
    )
  • Methods: GET read | POST create | PUT replace | PATCH partial | DELETE remove
  • Versioning: URL path
    /api/v1/
  • Response:
    { data, pagination?: { page, limit, total, totalPages } }
  • Errors:
    { error: { code, message, details? } }
  • Queries:
    ?page=1&limit=20&status=active&sort=createdAt,desc
  • Return
    Location
    header on 201. Use 204 for successful DELETE with no body.
  • 资源命名:使用复数名词(
    /users
    ),最多嵌套2层(
    /users/:id/orders
  • 请求方法:GET(读取)| POST(创建)| PUT(替换)| PATCH(部分更新)| DELETE(删除)
  • 版本控制:URL路径
    /api/v1/
  • 响应格式
    { data, pagination?: { page, limit, total, totalPages } }
  • 错误响应
    { error: { code, message, details? } }
  • 查询参数
    ?page=1&limit=20&status=active&sort=createdAt,desc
  • 201状态码返回时需附带
    Location
    响应头。成功删除且无返回体时使用204状态码。

Async Patterns

异步模式

PatternUse When
async/await
Sequential operations
Promise.all
Parallel independent ops
Promise.allSettled
Parallel, some may fail
Promise.race
Timeout or first-wins
Never
readFileSync
/ sync methods in production. Offload CPU work to worker threads. Stream large payloads.
模式使用场景
async/await
串行操作
Promise.all
并行独立操作
Promise.allSettled
并行操作,允许部分失败
Promise.race
超时控制或先完成优先
生产环境中绝不要使用
readFileSync
/同步方法。将CPU密集型任务卸载到工作线程。流式处理大负载数据。

Discipline

开发准则

  • For non-trivial changes, pause and ask: "is there a more elegant way?" Skip for obvious fixes.
  • Simplicity first — every change as simple as possible, impact minimal code
  • Only touch what's necessary — avoid introducing unrelated changes
  • No hacky workarounds — if a fix feels wrong, step back and implement the clean solution
  • 对于非琐碎的代码变更,先暂停思考:“有没有更优雅的实现方式?”明显的修复可跳过此步骤。
  • 简洁优先——每个变更尽可能简单,影响代码范围最小
  • 只修改必要的代码——避免引入无关变更
  • 拒绝投机取巧的解决方案——如果某个修复感觉不对劲,退一步实现更简洁的方案

References

参考资料

  • TypeScript config — tsconfig, ESM, branded types, compiler performance
  • Security — JWT, password hashing, rate limiting, OWASP
  • Database & production — connection pooling, transactions, Docker, logging
  • TypeScript配置 — tsconfig、ESM、品牌类型、编译器性能
  • 安全防护 — JWT、密码哈希、请求频率限制、OWASP
  • 数据库与生产环境 — 连接池、事务、Docker、日志记录