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 }
})
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:
- Get a list of each component
- Import that component
- 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')
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
}
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)
})
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)
})
Top comments (8)
Thank you, this helps.
just note: globEager is now deprecated.
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.
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!
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.
Nice post!
thank you)
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.
Thank you!