首页龙虾技能列表 › Nodejs Patterns — Node.js Patterns — Node.js 后端开发模式

Nodejs Patterns — Node.js Patterns — Node.js 后端开发模式

v1.0.0

提供生产级 Node.js 后端开发模式,包括 Express/Fastify 设置、分层架构、中间件、错误处理、验证、数据库集成、身份验证和缓存等。适用于构建 REST API、设置 Node.js 服务器、实现身份验证、集成数据库、添加验证/缓存和结构化后端应用。

2· 2,000·13 当前·13 累计
by @wpank·MIT-0
下载技能包
License
MIT-0
最后更新
2026/2/26
安全扫描
VirusTotal
无害
查看报告
OpenClaw
安全
medium confidence
此技能仅提供指令和 Node.js 后端开发模式代码片段,能力与目的一致,但源码/安装指南不清晰,使用前应验证。
评估建议
此技能是一致的 Node.js 后端开发模式集合,仅包含指令,无可执行代码。使用前请:(1)验证技能来源/作者;(2)不要在示例中输入生产密钥;(3)在沙盒/分支中审查和测试代码;(4)优先从官方仓库安装依赖。...
详细分析 ▾
用途与能力
技能名称/描述与 SKILL.md 内容匹配,包括分层架构、Express/Fastify 代码片段、错误处理、验证、身份验证、数据库和缓存。技能不请求无关的凭据、二进制文件或配置路径。
指令范围
SKILL.md 仅包含 Node.js 服务器的代码示例和指南,不指示代理读取系统文件、传输外部数据或超出典型用途访问环境变量。无广泛或开放式指令授予额外数据访问。
安装机制
无安装规格(仅指令),低风险。README 安装示例中有一些小问题(如使用 'npx add' 与 GitHub 树 URL 和本地 ~/.ai-skills 路径的引用),不明确但不表明恶意行为,使用前应验证。
凭证需求
技能不声明任何必需的环境变量或凭据。内联示例引用 process.env(典型的应用配置),但 SKILL.md 中没有内容指示代理泄露机密或要求无关令牌。
持久化与权限
技能仅包含指令,无安装步骤写入磁盘,'always' 为 false。不请求提升的持久性或系统范围的配置更改。
安全有层次,运行前请审查代码。

License

MIT-0

可自由使用、修改和再分发,无需署名。

运行时依赖

无特殊依赖

版本

latestv1.0.02026/2/10

初始发布 — 生产级 Node.js 后端模式。包括 Express 和 Fastify 设置、分层架构、错误处理、验证、JWT 身份验证、数据库集成、安全和可维护性指南。

● 无害

安装命令 点击复制

官方npx clawhub@latest install nodejs-patterns
镜像加速npx clawhub@latest install nodejs-patterns --registry https://cn.clawhub-mirror.com

技能文档

使用 TypeScript 构建可扩展、可维护的 Node.js 后端应用程序的模式。

永远不要

  • 永远不要在代码中存储密钥 - 使用环境变量,永远不要硬编码凭证
  • 永远不要跳过输入验证 - 使用 Zod/Joi 在中间件层验证所有输入
  • 永远不要在生产环境中暴露错误详情 - 返回通用消息,在服务器端记录详情
  • 永远不要使用 any 类型 - TypeScript 类型防止运行时错误
  • 永远不要跳过错误处理 - 始终包装异步处理器,使用全局错误中间件
  • 永远不要使用同步操作 - 对 I/O 使用 async/await,切勿在处理器中使用 fs.readFileSync
  • 永远不要信任客户端输入 - 清理、验证并参数化所有查询

何时使用

  • 使用 Express 或 Fastify 构建 REST API
  • 设置中间件管道和错误处理
  • 实现身份验证和授权
  • 使用连接池和事务集成数据库
  • 添加验证、缓存和速率限制

项目结构 — 分层架构

src/
├── controllers/     # 处理 HTTP 请求/响应
├── services/        # 业务逻辑
├── repositories/   # 数据访问层
├── models/         # 数据模型和类型
├── middleware/     # 认证、验证、日志、错误
├── routes/        # 路由定义
├── config/        # 数据库、缓存、环境配置
└── utils/         # 辅助工具、自定义错误、响应格式化

控制器处理 HTTP 事务,服务包含业务逻辑,仓储抽象数据访问。每一层只能调用其下一层。

Express 设置

import express from "express";
import helmet from "helmet";
import cors from "cors";
import compression from "compression";

const app = express();

app.use(helmet()); app.use(cors({ origin: process.env.ALLOWED_ORIGINS?.split(",") })); app.use(compression()); app.use(express.json({ limit: "10mb" })); app.use(express.urlencoded({ extended: true, limit: "10mb" }));

Fastify 设置

import Fastify from "fastify";
import helmet from "@fastify/helmet";
import cors from "@fastify/cors";

const fastify = Fastify({ logger: { level: process.env.LOG_LEVEL || "info" }, });

await fastify.register(helmet); // ... 其他插件

中间件

// 验证中间件
const validateRequest = (schema: ZodSchema) => {
  return (req: Request, res: Response, next: NextFunction) => {
    try {
      schema.parse(req.body);
      next();
    } catch (error) {
      res.status(400).json({ error: "Validation failed", details: error });
    }
  };
};

// 速率限制 import rateLimit from "express-rate-limit";

const limiter = rateLimit({ windowMs: 15 60 1000, // 15 分钟 max: 100, // 每个 IP 限制 100 个请求 });

app.use("/api/", limiter);

// 认证中间件 const authenticate = (req: Request, res: Response, next: NextFunction) => { const token = req.headers.authorization?.split(" ")[1]; if (!token) { return res.status(401).json({ error: "No token provided" }); } try { const decoded = jwt.verify(token, process.env.JWT_SECRET!); (req as any).user = decoded; next(); } catch { res.status(401).json({ error: "Invalid token" }); } };

错误处理

// 自定义错误类
class AppError extends Error {
  constructor(
    public statusCode: number,
    public message: string,
    public isOperational = true
  ) {
    super(message);
  }
}

// 全局错误处理器 app.use((err: Error, req: Request, res: Response, next: NextFunction) => { if (err instanceof AppError) { return res.status(err.statusCode).json({ error: err.message, }); } // 生产环境不暴露详情 console.error("Server error:", err); res.status(500).json({ error: process.env.NODE_ENV === "production" ? "Internal server error" : err.message, }); });

数据验证

import { z } from "zod";

// 创建验证 schema const createUserSchema = z.object({ email: z.string().email(), password: z.string().min(8), name: z.string().min(2).optional(), });

const updateUserSchema = createUserSchema.partial();

// 在控制器中使用 const createUser = async (req: Request, res: Response) => { const data = createUserSchema.parse(req.body); // ... 创建用户 };

数据库集成

// 仓储模式
class UserRepository {
  constructor(private db: Pool) {}
  
  async findById(id: string): Promise {
    const result = await this.db.query(
      "SELECT  FROM users WHERE id = $1",
      [id]
    );
    return result.rows[0] || null;
  }
  
  async create(data: CreateUserData): Promise {
    const result = await this.db.query(
      INSERT INTO users (email, password_hash, name) 
       VALUES ($1, $2, $3) RETURNING ,
      [data.email, data.passwordHash, data.name]
    );
    return result.rows[0];
  }
}

身份验证

import jwt from "jsonwebtoken";
import bcrypt from "bcrypt";

// JWT 签名 const signToken = (userId: string): string => { return jwt.sign( { userId }, process.env.JWT_SECRET!, { expiresIn: "7d" } ); };

// 密码哈希 const hashPassword = async (password: string): Promise => { return bcrypt.hash(password, 12); };

// 密码验证 const verifyPassword = async ( password: string, hash: string ): Promise => { return bcrypt.compare(password, hash); };

缓存

import Redis from "ioredis";

const redis = new Redis(process.env.REDIS_URL);

// 缓存中间件 const cacheMiddleware = (key: string, ttl: number = 300) => { return async (req: Request, res: Response, next: NextFunction) => { const cached = await redis.get(key); if (cached) { return res.json(JSON.parse(cached)); } // 拦截响应 const originalJson = res.json.bind(res); res.json = (data: any) => { redis.setex(key, ttl, JSON.stringify(data)); return originalJson(data); }; next(); }; };

速率限制

// 滑动窗口速率限制
const slidingWindowLimiter = async (
  key: string,
  limit: number,
  window: number
): Promise => {
  const now = Date.now();
  const windowStart = now - window;
  
  // 移除旧请求
  await redis.zremrangebyscore(key, 0, windowStart);
  
  // 计算当前请求数
  const count = await redis.zcard(key);
  
  if (count >= limit) {
    return false;
  }
  
  // 添加新请求
  await redis.zadd(key, now, ${now}-${Math.random()});
  await redis.expire(key, Math.ceil(window / 1000));
  
  return true;
};

配置管理

import dotenv from "dotenv";

dotenv.config();

export const config = { port: parseInt(process.env.PORT || "3000", 10), nodeEnv: process.env.NODE_ENV || "development", database: { host: process.env.DB_HOST!, port: parseInt(process.env.DB_PORT || "5432", 10), name: process.env.DB_NAME!, user: process.env.DB_USER!, password: process.env.DB_PASSWORD!, }, redis: { url: process.env.REDIS_URL!, }, jwt: { secret: process.env.JWT_SECRET!, expiresIn: process.env.JWT_EXPIRES_IN || "7d", }, };

日志

import pino from "pino";

const logger = pino({ level: process.env.LOG_LEVEL || "info", transport: process.env.NODE_ENV !== "production" ? { target: "pino-pretty" } : undefined, });

// 使用 logger.info({ userId: req.user?.id }, "Request received"); logger.error({ err, userId: req.user?.id }, "Request failed");

最佳实践

  • 分层架构 - 控制器→服务→仓储→数据库
  • 验证 - 在中间件层验证所有输入
  • 错误处理 - 使用全局错误处理器和自定义错误类
  • 安全 - 使用 helmet、cors、速率限制
  • 缓存 - Redis 缓存频繁访问的数据
  • 类型 - 始终使用 TypeScript 类型,避免 any
  • 配置 - 环境变量管理所有配置
  • 日志 - 结构化日志便于调试
数据来源:ClawHub ↗ · 中文优化:龙虾技能库
OpenClaw 技能定制 / 插件定制 / 私有工作流定制

免费技能或插件可能存在安全风险,如需更匹配、更安全的方案,建议联系付费定制

了解定制服务