UglifyJS - Mangle 函数但保留 Function.prototype.name

UglifyJS - Mangle functions but preserve Function.prototype.name

使用 UglifyJS 时,函数名称会被破坏,除非 keep_fnames 设置为 true。例如,以下 Typescript 代码:

class Test {}
console.log(Test.name);

编译为 JS 为:

function Test() {}
console.log(Test.name);

将被丑化为:

function t() {}
console.log(t.name);

并输出 t 而不是 test 到控制台。

有没有办法(other than using keep_fnames option)在丑化后保留name属性? (我不想使用 keep_fnames:true 因为它会大大增加包的大小。

我想到的可能的解决方案:

Is there a way (other than using keep_fnames option) to preserve the name property after uglification...

保持正确名称的唯一机制是该名称出现在输出文件中,因此简短的回答是否定的。如果您想使用 prototype.name,您需要保留该名称。

备选方案包括:

  1. 添加一个额外的 属性 包含名称,这可能会引入错误并且仍会在您的文件中占用 space
  2. 正在寻找一种工具,可以使用字符串值预编译 prototype.name 的所有用法...我不知道有没有,但你永远不知道!

正如所解释的,Function.prototype.name在客户端代码中不能依赖,因为函数原始名称的信息将随着缩小过程而被破坏。防止它被重命名是快速而肮脏的修复。

name 在某些浏览器中是只读且不可配置的,因此执行类似

的操作
class Test {
  static get name() {
    return 'Test';
  }
}

function Test() {}
Object.defineProperty(Test, 'name', { configurable: true, value: 'Test' });

将在大多数浏览器中修复它,但会在其余浏览器中导致模糊的兼容性问题(例如,Android 4.x 浏览器)。

执行此操作的正确方法是 从不依赖客户端代码中的 name 除了调试之外的任何事情。至于Node.js和Electron,就看代码是否需要混淆了。

如果 class 或函数应该存在字符串标识符,则可以选择另一个静态 属性 名称,例如id 或不受支持但常规 displayName.