Dans Vue, import.meta.glob est une fonctionnalité fournie par Vite pour importer dynamiquement des ficheirs. L'option eager: true permet de charger les fichiers de manière synchrone, au lieu du chargemant asynchrone par défaut.
Par défaut, import.meta.glob retourne un objet contenant des chemins de modules et des fonctions d'importation asynchrone, chargeant les modules à la demande (chargement paresseux). En définissant { eager: true }, Vite charge immédiatement tous les fichiers correspondants lors de la construction et les inclut directement dans l'objet résultat en tant que modules résolus. Cela signifie que le contenu des fichiers est disponible instantanément, sans requêtes asynchrones supplémentaires.
const importedModules = import.meta.glob('./components/*.vue', { eager: true });
Format de sortie avec eager: true : Chaque module a une propriété default contenant directement l'objet composant Vue.
{
'./components/WidgetA.vue': { default: VueComponent },
'./components/WidgetB.vue': { default: VueComponent },
// ...
}
Sans eager (défaut, eager: false) : Chaque module est une fonction retournant une Promesse, nécessitant un appel manuel pour charger le module.
{
'./components/WidgetA.vue': () => import('./components/WidgetA.vue'),
'./components/WidgetB.vue': () => import('./components/WidgetB.vue'),
// ...
}
Exemple avec eager: true
<template>
<div>
<!-- Composant dynamique, rendu basé sur la valeur de selectedWidget -->
<component
ref="widgetRef"
:is="activeComponent"
/>
</div>
</template>
<script setup>
import { ref, computed } from 'vue';
const props = defineProps(['widgetName']);
const widgetRef = ref(null);
const availableWidgets = {};
const widgetFiles = import.meta.glob('./components/*.vue', { eager: true });
for (const filePath in widgetFiles) {
const fileModule = widgetFiles[filePath];
const widgetId = filePath.split('/').pop()?.replace('.vue', '');
availableWidgets[widgetId] = fileModule.default;
}
const activeComponent = computed(() => {
const requestedName = props.widgetName;
if (requestedName && availableWidgets[requestedName]) {
return availableWidgets[requestedName];
}
return null;
});
defineExpose({});
</script>
<style lang="scss" scoped></style>
Exemple avec eager: false
<template>
<div>
<component
ref="widgetRef"
:is="activeComponent"
v-if="activeComponent"
/>
</div>
</template>
<script setup>
import { ref, computed, shallowRef } from 'vue';
const props = defineProps(['widgetName']);
const widgetRef = ref(null);
const loadedWidgets = ref({});
const widgetFiles = import.meta.glob('./components/*.vue', { eager: false });
const currentWidget = shallowRef(null);
const loadWidget = async (name) => {
if (loadedWidgets.value[name]) {
return loadedWidgets.value[name];
}
const matchingPath = Object.keys(widgetFiles).find((key) =>
key.split('/').pop().replace('.vue', '') === name
);
if (matchingPath && widgetFiles[matchingPath]) {
const module = await widgetFiles[matchingPath]();
loadedWidgets.value[name] = module.default;
return module.default;
}
return null;
};
const activeComponent = computed(() => {
const name = props.widgetName;
if (name) {
if (loadedWidgets.value[name]) {
return loadedWidgets.value[name];
}
loadWidget(name).then((component) => {
currentWidget.value = component || null;
});
}
return currentWidget.value;
});
defineExpose({});
</script>
<style lang="scss" scoped></style>
Raisons d'utiliser eager: true
Dans ce contexte, les composants de widgets sont limités en nombre et doivent être disponibles immédiatement au chargement de la page, évitant les délais de chargement asynchrone. Avec eager: false, un appel manuel via widgetFiles[path]() est requis pour charger les composants de manière asynchrone, ce qui peut entraîner un état de chargement temporaire lors du changement, impactant l'expérience utilisateur.
Considérations importantes
- Performance :
eager: trueinclut tous les composants correspondants dans le bundle initial. Si le nombre de composants est élevé, cela peut augmenter le temps de chargement initial. Il faut évaluer sieager: falsepour un chargement à la demande est plus approprié. - Chemins : Assurez-vous que le pattern
./components/*.vuecorerspond correctement aux fichiers cibles ; le chemin est relatif au fichier actuel. - Noms des composants : La prop
widgetNamedoit correspondre au nom du fichier (sans l'extension.vue), par exemple 'WidgetA'. - Spécifique à Vite :
import.meta.globest une fonctionnalité Vite ; pour les projets non Vite, d'autres solutions d'importation dynamique doivent être envisagées.