如何通过Terser压缩Math、Number等内置对象的调用代码?
Terser实现Math/Number等内置对象调用压缩的方案
不需要手动在源码中维护const min = Math.min这类别名,通过Terser压缩阶段的配置即可自动完成全项目重复内置调用的简化,全程无业务代码侵入。
核心配置
Terser默认不会主动替换内置对象调用,本质是默认配置下无法保证Math、Number等全局内置对象的静态方法没有被业务代码篡改,贸然替换会引发逻辑错误。通过以下配置即可开启自动压缩:
{ compress: { // 标记代码运行在ES Module环境,Terser会基于模块作用域的安全性,自动识别未被篡改的内置API // 非模块环境可删除该行,开启下方unsafe配置即可 module: true, // 非模块环境开启,允许Terser假设标准内置对象未被篡改 unsafe: true, // 开启变量归约、折叠能力,自动提取重复调用的内置方法为短名常量 collapse_vars: true, reduce_vars: true, // 标记属性访问无副作用,提升内置方法提取命中率 pure_getters: "strict", // 按需登记项目中高频使用的内置方法为纯函数,标记后Terser会优先提取这类重复调用 pure_funcs: [ "Math.min", "Math.max", "Math.floor", "Math.ceil", "Math.round", "Math.abs", "Math.sqrt", "Math.pow", "Number.parseInt", "Number.parseFloat" ], // 设置2-3轮压缩,覆盖遗漏的重复调用 passes: 2 }, mangle: true }
配置生效后,Terser会自动在对应作用域顶部注入类似const a = Math.min的短名常量,所有同作用域内的Math.min调用都会被替换为a(),和手动写别名的优化效果完全一致。
注意事项
- 不要尝试通过
mangle.properties压缩内置属性名,该选项默认跳过JS标准内置属性,强行配置规则会直接导致代码运行报错。 - 如果你的运行环境存在篡改内置对象的逻辑(比如自定义覆盖
Math.min实现polyfill),不要开启unsafe: true,否则会导致自定义逻辑失效。纯ES Module环境、无内置对象篡改逻辑时,仅开启module: true即可安全完成压缩,不会触发其他非预期的压缩规则。 - 如果存在少量未被提取的内置调用,适当增加
passes的轮次即可,一般2轮压缩就能覆盖99%以上的重复调用场景。
进阶可控方案
如果不想全量开启unsafe模式引入其他压缩规则,可以基于Terser的AST遍历能力写一个极简的自定义压缩插件,遍历所有成员表达式节点,识别Math.xxx、Number.xxx这类内置调用,自动替换为提前注入的短名变量即可,规则可控性更高,不会影响其他压缩逻辑。
千处级别Math调用的项目中,该优化一般能减少1-3KB的产物体积,无额外源码维护成本。
内容的提问来源于stack exchange,提问作者Waruyama
相关产品推荐
相关产品推荐

