Class.name 在 uglify / webpack 用于生产后,每个 class 总是 'e'

Class.name always 'e' for every class after uglify / webpack for production

我有一个在开发环境中运行良好但在生产环境中无法运行的应用程序,这是由 uglify 引起的(我认为是)

我有一个用户构建的数据,我将其保存到文件或 LocalStorage(json 在这两种情况下都没有关系)。

该结构由 3 种类型的节点构建而成。我已经在基础 class 中实现了 属性(全部继承自一个 class):type =this.constructor.name 并且它在开发中运行良好。当我加载应用程序并读取缓存时,我通过 JSON 并使用 switch (obj.type) case class1.name... 等重建对象。它运行良好。

然而,当我为生产而构建时,当我调用 class1.nameclass2.nameclass3.name 时,这一切都是 returns e 这使得无法恢复适当的对象...

我不认为这是特定于框架的问题,但如果有人需要知道我使用 VueJS 和 Quasar Framework 进行构建。

有什么想法吗?

constructor.name 或任何其他函数 name 属性 不应在客户端 JavaScript 中依赖,正是因为在生产环境中缩小是必须的,并且函数具有有意义名称的函数成为单字母命名函数。 e 是使用 UglifyJS 缩小的函数的通用名称。这就是 uglified JS 文件比 unminified 文件占用空间小得多的原因。

如果 function/class 名称用于调试以外的任何用途,则应将它们明确指定为静态属性。由于在某些引擎中无法重新定义 name,因此可以使用 non-standard displayName(也可用于调试)或任何其他 属性 名称:

class Foo {
  static get id() { return 'Foo' }
  ...
}

或者:

class Foo {
  ...
}
Foo.id = 'Foo';

对于后来者

Webpack 使用 UglifyJS 压缩和隐藏代码的各个方面(称为 'mangle'),具体针对您的问题,它将所有 类 转换为 e,如果你想保留你的类名 and/or 函数名,你必须在你的 webpack 配置或 cli 中指定不要这样做。

您可以通过删除最小化或创建您自己的优化实例来禁用此行为,如图所示 here

根据您的目标,您还可以使用以下方法。在我的例子中,我只需要能够区分 class 类型,所以下面的就足够了:

class MyClass {
    constructor(){
        this.createClassId()
    }
    createClassId(){
        if(!this.constructor.prototype._customClassId){
        this.constructor.prototype._customClassId = uuidv4() //you choose what you want this _customClassId to be. Or have a look at nanoId which can produce shorter names
    }
}

然后 new MyClass()._customClassId 对于相同 class 的所有实例都是相同的。并且,例如,如果您从 MyClass 继承,subclasses 将具有相同的 _customClassId 月所有 subclasses 的实例,但它与什么不同父 class 持有。

如果您需要控制每个 class 的确切 _customClassId 应该是什么,您也可以这样做,尽管它需要使用继承进行更多设置,如下所示:

class MyBaseClass {
    constructor(){
        this.createClassId()
    }
    createClassId(){
        if(!this.constructor.prototype._customClassId){
        this.constructor.prototype._customClassId = this.getCustomClassName() //you choose what you want this _customClassId to be. Or have a look at nanoId which can produce shorter names
    }

    getCustomClassName(){
        throw new Error("Make sure to implement 'getCustomClassName' in your subclass")
    }

}

然后您可以扩展每个 class,您需要从这个 MyBaseClass 访问它们的 classType/className 并覆盖 getCustomClassName 以提供您的值。