schema-dsl 最佳实践
用途: 帮助你写出高质量、高性能的 Schema 代码
更新: 2026-05-08
📑 目录
Schema 设计原则
1. 简单字段用纯 DSL
推荐:
不推荐(过度复杂):
原则: 能用 DSL 字符串表达的,就不要用链式调用。
2. 复杂验证用链式调用
适合链式调用的场景:
- 需要正则验证
- 需要自定义错误消息
- 需要自定义验证器
- 需要标签(label)
示例:
3. 使用预设验证器
schema-dsl 提供了常用的预设验证器,开箱即用:
可用预设:
username(preset?)- 用户名验证password(strength?)- 密码强度验证phone(country?)- 手机号验证slug()- URL slug 验证
4. 避免过深的嵌套
不推荐(嵌套过深):
推荐(拆分或扁平化):
原则: 嵌套深度建议不超过 3-4 层。
性能优化
1. 预编译 Schema
不推荐(每次都编译):
推荐(预编译):
收益: 复用已编译结果可以显著减少重复编译成本,尤其适合热点路由和高频校验路径。
2. 启用缓存
3. 批量验证
不推荐(循环验证):
推荐(批量验证):
ℹ️ 如果你确实要直接传入自己创建的 Ajv 实例,请先确保它已经注册了与 schema-dsl 生成 schema 匹配的格式和关键字;对大多数项目来说,直接复用
validator.getAjv()更稳妥。
4. 优化正则表达式
不推荐(可能导致 ReDoS):
推荐(安全高效):
工具: 使用 regexploit 检测危险正则。
5. 避免在循环中创建 Schema
不推荐:
推荐:
安全性考虑
1. 限制用户输入的正则
危险:
原因: 用户可能输入恶意正则导致 ReDoS 攻击。
安全做法:
2. 清理错误消息
生产环境不要暴露敏感信息:
3. 限制 Schema 复杂度
4. 防止原型污染
错误处理
1. 统一错误格式
推荐的错误处理中间件:
2. 友好的错误消息
使用 label 和自定义消息:
效果:
3. 处理外部异步校验错误
.custom()当前仅支持同步函数;涉及数据库、RPC、HTTP 等异步检查时,请在基础校验通过后于业务层单独执行。
代码组织
1. 集中管理 Schema
推荐的项目结构:
schemas/user.schema.js:
schemas/index.js:
routes/user.routes.js:
2. Schema 复用
使用 SchemaUtils:
生产环境建议
1. 环境配置
2. 监控和日志
3. 健康检查
4. 定期维护
性能基准参考
缓存命中前后通常能显著降低重复编译开销,但绝对耗时会受到机器性能、Node 版本、schema 复杂度、数据规模和命中率影响,不建议把某组固定毫秒数当成通用基准。
更稳定的结论:
- 复用同一个 schema 对象或
Validator实例,通常比每次请求都重新编译更快 - schema 越复杂、重复验证次数越多,缓存收益通常越明显
- 批量验证总耗时主要取决于单条 schema 复杂度和数据规模,不应使用固定毫秒数做容量承诺
如需当前可复查的吞吐量对比,请以维护中的 benchmark 结果和 FAQ 中同步的性能数据为准。
总结
遵循这些最佳实践,你的 schema-dsl 代码将具备:
✅ 高性能 - 通过预编译和缓存
✅ 高安全性 - 避免常见安全陷阱
✅ 高可维护性 - 清晰的代码组织
✅ 高可用性 - 完善的错误处理
延伸阅读
对应示例文件
示例入口: best-practices.ts
说明: 展示“简单字段用纯 DSL、复杂字段局部使用 Builder、字段库复用”的推荐组合,以及成功 / 失败两条验证路径。