Marek Urbanowicz
Marek Urbanowicz

Reputation: 13644

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

I have an app which is working great in development enviroment but it is not working in production, which is caused by uglify (I think so)

I have a data which user builds and I am saving that either to file or to LocalStorage (json in both cases so doesn't matter).

The structure is built from 3 type of nodes. I have implemented property in the base class ( all inherit from one class): type =this.constructor.name and it is working great in development. When I load the app and read the cache, I go through the JSON and rebuild objects using switch (obj.type) case class1.name... etc. It is working well.

However, when I build for production, when I call class1.name or class2.name or class3.name it all returns e which makes it impossible to restore proper objects...

I do not think it is framework specific issue, but if someone would need to know I build using VueJS with Quasar Framework.

Any ideas?

Upvotes: 6

Views: 5038

Answers (3)

vir us
vir us

Reputation: 10715

Depending on your goal you can also use the below approach. In my case I just needed to be able to distinguish between class types so the below was sufficient:

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
    }
}

then new MyClass()._customClassId would be the same for all instances of the same class. And if, for example, you inherit from MyClass, the subclasses will have the same _customClassId month all instances of subclasses but it will be different from what the parent class holds.

If you need to control what exactly _customClassId should be for each class, you can do it as well, though it will require a bit more setup using inheritance like below:

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")
    }

}

Then you can extend every class where you need to access their classType/className from this MyBaseClass and override getCustomClassName providing your value.

Upvotes: 1

steff_bdh
steff_bdh

Reputation: 1188

For whoever comes after

Webpack uses UglifyJS to compress and hide aspects of your code (referred to as 'mangle'), with regards to your question specifically, it transforms all your classes to e, you have to specific either in your webpack config or cli to not do this if you'd like to preserve your classnames and/or function names.

You can disable this behavior by removing the minimization or creating your own optimization instance as shown here

Upvotes: 1

Estus Flask
Estus Flask

Reputation: 222528

constructor.name or any other function name property should never be relied in client-side JavaScript, exactly because minification is a must in production environment, and functions with meaningful names become one-letter named functions. e is a common name for a function minified with UglifyJS. This is the reason why uglified JS file has much lesser footprint than unminified file.

If function/class names are used for anything but debugging, they should be explicitly specified as static properties. Since name cannot be redefined in some engines, non-standard displayName (can also be useful for debugging) or any other property name can be used:

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

Or:

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

Upvotes: 11

Related Questions