Why You Shouldn’t Use Vue.component

Mitchell Garcia
Front-End Society
Published in
4 min readJan 24, 2018

One of my favorite features of VueJS as a framework is its passive enforcement of good software development practices.

By design it does not enforce any coding style or architecture, but it makes it so easy to write things correctly, you might as well just do so.

One example is the scoped attribute offered by the vue-loader.

Writing CSS that only applies to a single component is usually a manual process. You can wrap your component in class, or use a naming convention like Atomic Design, BEM or SMACSS. It’s not incorrect to do so, but it is manual. scoped does all this hard work for you, in a single keyword.

Components are another example. Most front-end engineers (and libraries) agree that components are how we should be building UIs. A VueJS app, at the end of the day, is literally just a collection of components.

So, you’re probably asking: why shouldn’t you use Vue.component?

Well…

Components using Vue.component are global

It’s always been about the globals. Since the dawn of time, we’ve been fighting globals.

What a global component means is — if Component A wants to use Component B, and Component B is global, Component B can just be dropped in Component A’s template, and it will render. There is nowhere else that Component A’s requirement on Component B is listed other than the code.

This is not optimal for a variety of reasons, including:

Globals Make It Harder To Refactor Code

Module bundlers are very popular nowadays. This is good. Modules make it easier to organize our code into separate files. This makes our code not only more DRY, but easier to refactor.

How? Well…

All our dependencies are explicit. For example, if module a were to be deleted, and module b is dependent on it, module b is now broken, and the bundler will tell you this.

This is an important feature in projects with more than one person working on them because it lowers the cognitive load of working on one module.

If the file requires a global variable, how do you know what it is? An object? A function? A class? There’s no way of knowing unless it’s commented, and even then, it’s probably incorrect. And even if it was correct at some point, it may have been overwritten, because Javascript let’s you do that to globals.

Using Vue.component is the same thing as using a global variable, and comes with the same problems.

<component-name> can be anything: a list, a dialog, a text box, a picture of a cat. Using Vue.component, the only way to find out what <component-name> actually looks like is to use your text editor’s Find All and search for ComponentName or component-name (see my point).

Naming Collisions

There is a risk with Vue.component that the name requested is already taken. This will throw an error that can only be resolved by renaming the component.

In theory, you should be able to change the name of a component to whatever you wish based on where it is. This is possible if the component is defined as an explicit dependency, which I outline how to do below (“What To Use Instead” section).

Breaks Tooling

Locally defined component’s props visible in autocomplete

Tooling is an important part of the equation. For Vue users who use VSCode, Vetur offers amazing support for .vue components.

One feature of Vetur is auto-complete for component props, provided the component is locally registered, not global. If the component is global, you get… nothing.

Globally defined component, props it needs are not showing

This is important because it acts as another layer of documentation for your components. If you come from a .NET background, you know how convenient it is to get a description of what is expected in your IDE.

For Vue components, you can get the same experience. All you need to do is add a note to the component’s definition:

then it will propagate in the autocomplete for that prop.

Notice how now ‘Prop example’ is visible in the dropdown

What To Use Instead Of Vue.component

I love technical articles with paragraphs of problems, and a sentence of solution.

It’s so easy. You can avoid all the issues outlined above by only using local registration for all your components.

This means instead of this:

// ComponentName.vue
export default Vue.component("ComponentName", {...})

do this:

// ComponentName.vue
export default {...}

So whenever you need to use ComponentName.vue, you do this:

// OtherComponentName.vue
import ComponentName from "./ComponentName.vue"
export default {
components: {
ComponentName
}
}

And now literally all of the problems with global components are solved.

Thank you for reading the Front-End Society Blog! You can follow me on Twitter for more content.

--

--