vue-class-component icon indicating copy to clipboard operation
vue-class-component copied to clipboard

"name" in @Component options is obfuscated (?) in build version

Open sp00x opened this issue 5 years ago • 9 comments

Repro: https://github.com/sp00x/vue-typescript-name-bug

2 components, Foo (ts) and Bar (js) registered as global components in main.ts using

import Foo from '@/components/Foo.vue';
import Bar from '@/components/Bar.vue';
Vue.component(Foo.name, Foo) // typescript
Vue.component(Bar.name, Bar) // javascript

With yarn serve it logs in the console:

in App.vue:

Foo.name = Foo
Bar.name = Bar

in main.ts

Foo.name = Foo
Bar.name = Bar

and renders

Foo:
foo
- Bar:
bar

With yarn build output it logs in the console:

in App.vue:

Foo.name = t
Bar.name = Bar

in main.ts

Foo.name = t
Bar.name = Bar

renders:

Foo: - Bar:
bar

Foo is a typescript SFC, where as Bar is a regular javascript SFC with export default { name: 'Bar' }

Seems like the typescript value is being obfuscated or uglified somehow?

sp00x avatar Mar 26 '20 23:03 sp00x

Similar issues, which even leads to some very strange and incosistence behaviors on ssr. Did you find any workaround or fix already?

simllll avatar Apr 01 '20 23:04 simllll

@simllll My current workaround is to register with a static, known name vue.component('Foo', Foo) ...which is not ideal, nope.

sp00x avatar Apr 02 '20 07:04 sp00x

Having the same issue. Hoping for quick resolution

vafl-brut avatar Apr 13 '20 18:04 vafl-brut

This is actually a side effect of terser webpack plugin. If you disable terser's mangling, things work fine. I added the following in my nuxt config in build.extend() function:

if (isServer) {
  // replace terser on server side with "mangle: false"
  config.optimization.minimizer = config.optimization.minimizer.map(o => {
	if (o.constructor.name === 'TerserPlugin') {
		return new TerserPlugin({
			cache: true,
			parallel: true,
			sourceMap: true, // Must be set to true if using source-maps in production
			terserOptions: {
				mangle: false
			}
		});
	}
	return o;
  });
}

simllll avatar Apr 13 '20 19:04 simllll

Thanks @simllll, this helped!

vafl-brut avatar Apr 14 '20 15:04 vafl-brut

That looks because we use class name to infer the component name. We probably need to remove this inference in the next major version as its behavior is inconsistent between builds.

ktsn avatar Apr 19 '20 11:04 ktsn

This worked for me in webpack4 without increasing the bundle size too much

module.exports = {
    optimization: {
        minimizer: [
            new TerserPlugin({
                terserOptions: {
                    keep_classnames: true,
                },
            }),
        ],
    },
}

Trinovantes avatar Nov 14 '20 10:11 Trinovantes

Trinovantes' proposition is far better than disabling the mangling altogether, as proposed by simllll. I'll just add that in my (legacy) project/setup, I had to tell terserjs to keep the function names, not the class names, because before the code is passed to terserjs, the code is already transpiled to es5. In other words, I had to do the following:

module.exports = {
    optimization: {
        minimizer: [
            new TerserPlugin({
                terserOptions: {
                    keep_fnames: true,
                },
            }),
        ],
    },
}

I did end up, however, upgrading the library (vue-slider-component) that uses vue-class-component under the bonnet, which also resolved the problem for me.


As a side note: it's regrettable that after 2 years, this still isn't fixed and released in the v7 of vue-class-component. This problem is so easy to run into.

d-ph avatar Oct 21 '22 13:10 d-ph

For future readers: when you refer to class-component name like that: Foo.name you refer to the name of the class itself. name property here is Function.name property, not Vue property. It will be obfuscated. You can get actual component name using Foo.options.name, that name property is Vue property, it will contain correct name set from options.

Kadeluxe avatar Aug 02 '23 11:08 Kadeluxe