generator 高复用与高性能的核心在于精准约束:显式不可变的输入输出契约、严格状态隔离、可控可跳过的 yield 粒度、零运行时反射。

要让 Generator 既容易复用,又跑得飞快,核心不在“写得多”,而在“约束得准”——用明确的契约替代自由发挥,用静态可推导性换运行时开销。
输入输出契约必须显式、不可变
Generator 不该猜测参数类型或默认行为。每个参数需标注类型、是否必填、取值范围;返回值结构固定,不因参数微调而改变字段名或嵌套层级。
- 用 TypeScript interface 或 JSON Schema 描述输入输出,而非注释或文档
- 禁止在 yield 前动态拼接模板、计算路径——所有字符串字面量、文件路径、配置键名必须可静态提取
- 如需条件分支,用 enum 控制,而非字符串匹配(例:用 TargetEnv.PROD 而非 env === 'production')
状态隔离与副作用收敛
Generator 执行过程不能依赖外部 mutable 状态(如全局变量、共享缓存对象、未克隆的入参),也不能主动修改入参或环境。
- 所有中间数据在函数作用域内声明,生命周期严格绑定于单次调用
- I/O 操作(读文件、请求 API)统一收口到独立的 loader 函数,Generator 仅接收 loader 返回的纯数据
- 缓存逻辑由调用方控制(如 memoize 包裹 loader),Generator 内部不实现 LRUCache 或 time-based invalidation
yield 粒度可控,且具备可跳过性
每次 yield 应代表一个逻辑上完整、可独立执行/跳过的最小单元(如“生成路由配置”“写入 index.html”),并携带可识别的 type 标识和轻量元数据。
- 避免 yield 字符串或原始对象;统一用 { type: 'WRITE_FILE', payload: { path, content } }
- 为每个 yield 添加 id 字段(如 'route-config-v2'),便于调用方按需过滤、重放或跳过
- 不 yield 大体积数据(如整个 AST 树),只 yield 操作指令 + 关键标识符,具体数据由 loader 按需加载
零运行时反射,全链路可静态分析
不使用 eval、Function constructor、require(variable)、Object.keys(obj) 等动态机制;所有模块引用、字段访问、类型判断必须在构建期确定。
- 模板渲染用预编译函数(如 EJS compile → function,非 render(str, data))
- 配置合并用字面量展开({ ...base, ...override }),不用 _.merge 或深拷贝工具
- 类型守卫用 isXXX(value): value is XXX,不用 typeof value === 'object' && value?.kind === 'xxx'
不复杂但容易忽略:高复用性来自接口稳定,极限效率来自放弃灵活性。Generator 不是万能胶,而是精密齿轮——每个齿形、转速、咬合位置都提前定义好,才能高速咬合、批量组装。










