DEV Community

Jake Dohm
Jake Dohm

Posted on

Auto-registering all your components in Vue 3 with Vite

Why auto-register components?

I'm actually a big fan of manually importing components in Vue applications. It makes it very clear where every component comes from, doesn't rely on ✨magic✨, and most IDEs can do auto-imports for you anyway so it's not much more work for you.

That said, in an environment where I'm not building an SPA, and I'm using Vue as a progressive enhancement tool, I want all of my components to be available in HTML. To make this happen, I have to register all of them in the root Vue instance....

import { createApp } from 'vue'
// import each component
import Fruits from './components/Fruits.vue'
import Vegetables from './components/Vegetables.vue'

const vueApp = createApp({
  // register each component
  components: { Fruits, Vegetables }
})
Enter fullscreen mode Exit fullscreen mode

This process is tedious, and makes component auto-registration totally worth it IMO.

How

So, to auto-register our components, we need to do a few things:

  1. Get a list of each component
  2. Import that component
  3. Register it on our Vue instance

Luckily, Vite has an amazing feature which takes care of steps #1 and #2 for us

Step 1+2: Glob Imports.

Glob Imports is feature of Vite that allows us to import multiple files based on a filepath.

There are two ways to use Glob Imports in Vite: lazy or eager. If you use the standard glob method, the imports will be processed as dynamic imports, so the components will be lazy-loaded. In our case, we want to import all of the components directly into our main bundle, so we'll use the globEager method.

Note: Glob Imports is a Vite feature, and is not part of any JS or "platform" standards.

Here's how Glob Imports works:

// import multiple components
const components = import.meta.globEager('./components')
Enter fullscreen mode Exit fullscreen mode

And here's the result of that import:

// code produced by vite

// magically autogenerated module imports
import * as __glob__0_0 from './components/Fruits.vue'
import * as __glob__0_1 from './components/Vegetables.js'

// our components variable now contains an object with key/values
// representing each module's path and definition
const components = {
  './components/Fruits.vue': __glob__0_0,
  './components/Vegetables.vue': __glob__0_1
}
Enter fullscreen mode Exit fullscreen mode

Step 3: Registering components

Now that we've actually imported each component, and we have a list containing the path and definition, we need to define these components on our Vue instance.

To do that, we'll loop over each entry in our components object, figure out the component's name based on the file name, and then register the component on our Vue instance.

Object.entries(components).forEach(([path, definition]) => {
  // Get name of component, based on filename
  // "./components/Fruits.vue" will become "Fruits"
  const componentName = path.split('/').pop().replace(/\.\w+$/, '')

  // Register component on this Vue instance
  vueApp.component(componentName, definition.default)
})
Enter fullscreen mode Exit fullscreen mode

Putting it all together

import { createApp } from 'vue'

const vueApp = createApp()

const components = import.meta.globEager('./components/*.vue')

Object.entries(components).forEach(([path, definition]) => {
  // Get name of component, based on filename
  // "./components/Fruits.vue" will become "Fruits"
  const componentName = path.split('/').pop().replace(/\.\w+$/, '')

  // Register component on this Vue instance
  vueApp.component(componentName, definition.default)
})
Enter fullscreen mode Exit fullscreen mode

Top comments (8)

Collapse
 
lukaszahorec profile image
Lukáš Záhorec

Thank you, this helps.

just note: globEager is now deprecated.

import.meta.globEager is now deprecated. Use import.meta.glob('*', { eager: true }) instead.

Collapse
 
elmassimo profile image
Máximo Mussini

Nice post!

Depending on your setup, you might also be able to use the following plugin:

github.com/antfu/vite-plugin-compo...

It has worked nicely in the few projects where I've added it.

Collapse
 
jakedohm_34 profile image
Jake Dohm

Hey Máximo! Yes, that's a super neat plugin.

That plugin works really nicely when all of your code is within JavaScript, like Single File Components. In my case, I'm using Vue components in twig/html that isn't processed by the Vue template compiler. So, I have to globally register them on the Vue instance.

So yeah, depends on the use-case but both are good!

Collapse
 
samsour profile image
samsour

This also works totally well in combination. Imagine you no longer have any component imports in your SFCs. Nevertheless, you have "exposable components" that you then register globally, which you can use in Twig/html. The components contained in them are automatically resolved.

Collapse
 
overtrue profile image
overtrue

Nice post!

Collapse
 
mod7ex profile image
Mourad EL CADI

thank you)

Collapse
 
sivavchandran profile image
Siva Chandran

How to import all components inside a folder in a particular component in vue 3 with vite ? The above example is for globally registering them. I want to register multiple components in a componeny.

Collapse
 
ostap profile image
Ostap Brehin

Thank you!