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
因为它会大大增加包的大小。
我想到的可能的解决方案:
- 正在编写一个硬编码函数名称
Test.name = 'Test'
的 Webpack 插件,但这不会起作用,因为 Function.prototype.name
是只读的 属性;
- 使用 Typescript 装饰器、元数据和反射 API,但
design:type
元数据不会为 类 发出,它只会为属性发出(我认为这是因为 Function.prototype.name
存在,但我猜他们错过了这个边缘案例?)。
Is there a way (other than using keep_fnames option) to preserve the name property after uglification...
保持正确名称的唯一机制是该名称出现在输出文件中,因此简短的回答是否定的。如果您想使用 prototype.name
,您需要保留该名称。
备选方案包括:
- 添加一个额外的 属性 包含名称,这可能会引入错误并且仍会在您的文件中占用 space
- 正在寻找一种工具,可以使用字符串值预编译
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
.
使用 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
因为它会大大增加包的大小。
我想到的可能的解决方案:
- 正在编写一个硬编码函数名称
Test.name = 'Test'
的 Webpack 插件,但这不会起作用,因为Function.prototype.name
是只读的 属性; - 使用 Typescript 装饰器、元数据和反射 API,但
design:type
元数据不会为 类 发出,它只会为属性发出(我认为这是因为Function.prototype.name
存在,但我猜他们错过了这个边缘案例?)。
Is there a way (other than using keep_fnames option) to preserve the name property after uglification...
保持正确名称的唯一机制是该名称出现在输出文件中,因此简短的回答是否定的。如果您想使用 prototype.name
,您需要保留该名称。
备选方案包括:
- 添加一个额外的 属性 包含名称,这可能会引入错误并且仍会在您的文件中占用 space
- 正在寻找一种工具,可以使用字符串值预编译
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
.