Vue-Js
Senior
Quiz-Vuejs-Senior
Nuxt
Ssr-Vue
Teleport
Suspense
Custom-Directives
Vue-Plugins
Vapor-Mode
Questions-Entretien-Vuejs-Senior
Qcm-Vuejs-Avance
Patterns-Vue
Performance-Vue
📝
Entretien Vue Senior : performance et patterns
20 questions Vue.js avancées : SSR avec Nuxt, Teleport, Suspense, custom directives, plugins, optimisation, Vapor mode et patterns avancés pour Senior.
Banque de révision : les 30 questions corrigées
Voici l'intégralité des 30 questions de « Entretien Vue Senior : performance et patterns », chacune avec sa bonne réponse et son explication. Le quiz interactif ci-dessus en tire une sélection aléatoire à chaque tentative — utilisez cette liste complète pour réviser.
Explication :
Le compilateur Vue 3 transforme les templates en fonctions de rendu optimisées. Le Static Hoisting extrait les nœuds statiques (qui ne dépendent d'aucune donnée réactive) hors de la fonction
render. Ces nœuds sont créés une seule fois et réutilisés, réduisant le travail du Virtual DOM.
Pour profiter au maximum du Static Hoisting, évitez d'utiliser des directives inutiles sur du contenu statique. Un
<h1>Titre Fixe</h1> pur sera hissé automatiquement.
Explication :
Les Patch Flags sont des nombres générés lors de la compilation. Ils indiquent si un élément contient du texte dynamique (
1 = TEXT), une classe dynamique (2 = CLASS), etc. Lors du diffing, Vue ne vérifie que les parties marquées, ignorant le reste.
C'est ce qui rend Vue 3 extrêmement performant. Contrairement à React qui compare tout l'arbre, Vue sait exactement quelles parties sont dynamiques.
Explication :
Quand des données réactives changent, Vue ne met pas à jour le DOM immédiatement. Il bufferise les changements et les vide à la fin du cycle actuel (
nextTick). Cela évite de rendre plusieurs fois si plusieurs données changent dans la même "tick".
Pour attendre que le DOM soit à jour après un changement :
await nextTick().
Explication :
Les fonctions de rendu (et JSX) offrent toute la puissance de JavaScript pour générer le Virtual DOM. Utiles pour : composants génériques (bibliothèques UI), rendu conditionnel complexe, manipulation dynamique de slots, ou quand on vient de React.
99% des cas sont couverts par les templates. N'utilisez les fonctions de rendu que quand les templates deviennent un obstacle.
Explication :
La Custom Renderer API (
createRenderer()) permet d'utiliser le système de réactivité et de composants de Vue pour cibler autre chose que le DOM. Exemples : Vue Canvas (rendu sur canvas), Vue-blessed (terminal), Weex/Uni-app (natif mobile).
Cette API est ce qui permet à des frameworks comme NativeScript-Vue ou Uni-app d'utiliser la syntaxe Vue pour des applications mobiles natives.
Explication :
La prop
to peut être dynamique : :to="teleportTarget". teleportTarget peut être un sélecteur ("#modal-container") ou une référence DOM (ref()). Idéal pour les systèmes de plugins où la cible n'est pas connue à l'avance.
Le contenu téléporté doit déjà exister dans le DOM avant que le Teleport ne soit monté. Pour des cibles dynamiques, créez l'élément cible dans
onMounted.
Explication :
Le Setup Store (fonction) offre une flexibilité totale : utilisation de composables, watchers, logique complexe. Inférence TypeScript parfaite. L'Options Store (objet
state/getters/actions) est plus familier aux utilisateurs Vuex et plus structuré.
Pour les nouveaux projets, privilégiez le Setup Store. Pour migrer depuis Vuex, l'Options Store facilite la transition.
Explication :
Un plugin est un objet avec une méthode
install(app, options). On peut y : enregistrer des composants globaux (app.component()), fournir des données (app.provide()), ajouter des propriétés globales (app.config.globalProperties), ou des directives (app.directive()).
Pour les propriétés globales, préfixez-les avec
$ pour éviter les conflits : app.config.globalProperties.$http = axios.
Explication :
defineSlots<{ default: (props: { item: Item }) => any; header: () => any }>() (Vue 3.3+) permet de typer les slots, leurs props, et leur présence (optionnel/requis). Le parent reçoit l'auto-complétion et la validation.
Pour rendre un slot optionnel, ajoutez
? : header?: () => any. Pour typer les props exposées au slot : default(props: { item: Item }).
Explication :
L'hydratation est le processus où Vue côté client prend le HTML statique généré par le SSR et y attache la réactivité, les événements et l'état. Vue 3.2+ supporte l'hydratation paresseuse (lazy hydration) : seules les parties visibles/interactives sont hydratées.
Des erreurs d'hydratation surviennent si le HTML serveur diffère du rendu client. Utilisez
<ClientOnly> pour le contenu spécifique au navigateur.
Explication :
Vite (basé sur Rollup) permet de contrôler le splitting :
manualChunks(id) { if (id.includes("node_modules/vue")) return "vue"; if (id.includes("node_modules/three")) return "three"; }. Cela crée des chunks nommés, améliorant le caching navigateur.
Regroupez les grosses dépendances peu mises à jour (three.js, chart.js) dans leur propre chunk pour maximiser le cache.
Explication :
L'interpolation
{{ }} échappe automatiquement les caractères dangereux (< → <). v-html désactive cette protection. Il ne faut JAMAIS utiliser v-html avec du contenu utilisateur non assaini.
Si vous devez utiliser v-html avec du contenu utilisateur, passez-le d'abord par DOMPurify :
import DOMPurify from "dompurify";.
Explication :
Vue DevTools (onglet Timeline) montre chaque rendu et sa cause.
onRenderTracked()/onRenderTriggered() (dev only) indiquent quelles dépendances déclenchent le rendu. En production, __VUE_PROD_DEVTOOLS__ active les DevTools.
Le flag
__VUE_PROD_HYDRATION_MISMATCH_DETAILS__ (Vue 3.4+) aide à déboguer les erreurs d'hydratation en production.
Explication :
Module Federation (Webpack 5) et son équivalent Vite (
@originjs/vite-plugin-federation) permettent de partager des composants Vue au runtime entre applications distinctes. Chaque micro-frontend se build indépendamment mais partage ses dépendances.
Partagez
vue, vue-router et pinia via le shared dans la config Module Federation pour éviter les doublons.
Explication :
defineCustomElement() (API officielle Vue 3.2+) convertit un composant Vue en un Custom Element standard. On peut l'utiliser dans n'importe quelle page HTML, avec React, Angular, etc. Les props sont mappées en attributs HTML.
Limitation : les Custom Elements ne supportent pas les slots nommés complexes ni le provide/inject. Testez bien votre composant avant de l'exporter.
Explication :
Sources de fuites : intervalles/timers non nettoyés, event listeners sur window/document non retirés, watchers créés avec
watchEffect sans onScopeDispose, références circulaires dans les composants gardés par KeepAlive. watchEffect() retourne une fonction de stop. Stockez-la et appelez-la dans onUnmounted(). Ou utilisez watchEffect() à l'intérieur de <script setup> qui nettoie automatiquement.
Explication :
effectScope() crée un scope qui peut contenir des watchers, computed, et autres effets. Quand le scope est détruit (scope.stop()), tous les effets sont nettoyés automatiquement. Essentiel pour les composables qui créent des watchers.
Dans vos composables, utilisez
effectScope() si vous créez dynamiquement des watchers après le setup initial. Sinon, <script setup> gère le scope automatiquement.
Explication :
Pour tester un composant dans Suspense : monter le composant, utiliser
flushPromises() (ou vi.runAllTimers() en Vitest) pour résoudre les promesses asynchrones, puis vérifier que le fallback a disparu et que le contenu est affiché.
Dans Vitest,
await vi.dynamicImportSettled() attend que tous les imports dynamiques soient résolus.
Explication :
Un système avancé :
router.beforeEach(async (to, from) => { const auth = useAuthStore(); if (to.meta.requiresAuth && !auth.isLoggedIn) return "/login"; if (to.meta.permissions && !auth.hasPermissions(to.meta.permissions)) return "/403" }). On peut chaîner plusieurs guards pour des vérifications progressives.
Stockez les permissions dans Pinia (chargées à l'authentification). Utilisez
to.matched pour vérifier les meta de toutes les routes imbriquées.
Explication :
Animation de route :
<RouterView v-slot="{ Component, route }"><Transition :name="route.meta.transition || 'fade'"><component :is="Component" :key="route.path" /></Transition></RouterView>. La clé basée sur route.path force la transition.
Pour des animations fluides entre listes et détails, utilisez l'animation FLIP (First, Last, Invert, Play) avec la bibliothèque auto-animate ou GSAP Flip.
Explication :
Optimisations clés : 1) Lazy loading des routes (
component: () => import()), 2) Analyse du bundle avec rollup-plugin-visualizer pour repérer les dépendances lourdes, 3) Compression Brotli/Gzip côté serveur/CDN, 4) Purge CSS (PurgeCSS) si vous utilisez Tailwind.
Activez
build.reportCompressedSize: false dans vite.config.js en CI pour accélérer le build.
Explication :
Avec Vite Library Mode, on peut builder une bibliothèque de composants Vue. On expose les composants (avec defineCustomElement pour l'interopérabilité), les composables, les tokens de design (CSS custom properties), et les types TypeScript.
Structurez votre lib avec :
src/components/ (composants), src/composables/ (logique), src/styles/ (tokens CSS). Exportez tout depuis src/index.ts.
Explication :
XState s'intègre parfaitement avec Vue via un composable :
const { state, send } = useMachine(machine). La machine définit tous les états possibles et les transitions, éliminant les bugs d'états impossibles.
Utilisez XState pour les flux complexes (formulaires multi-étapes, processus de paiement, lecteur audio). Le Visualizer XState aide à concevoir et déboguer.
Explication :
Vue Macros est une bibliothèque qui étend le compilateur Vue avec des fonctionnalités avancées non (encore) intégrées :
definePropsRefs() (props réactives), defineRender() (render function dans setup), booleanMode pour v-model, etc. definePropsRefs() transforme les props en refs, permettant de les destructure sans perdre la réactivité.
Explication :
Vue 3 : excellent équilibre performance/DX grâce aux Patch Flags et au Static Hoisting. Svelte : le plus petit bundle (compile away) et réactivité fine. React : écosystème immense, RSC modernes, mais Virtual DOM complet plus coûteux en CPU.
Le meilleur framework dépend de votre contexte. Vue brille pour les applications interactives avec un excellent DX. Les benchmarks JS Framework montrent que les trois sont suffisamment rapides.
Explication :
Vue 3 a supprimé le
$on/$emit global de Vue 2. On utilise mitt (minuscule, 200 octets) ou on crée son propre composable : const listeners = new Map(); export function useBus() { return { on, emit } }.
Préférez provide/inject ou Pinia pour la communication entre composants. L'Event Bus n'est utile que pour des cas très spécifiques de communication non hiérarchique.
Explication :
Approche complète : 1) Composants headless accessibles (Radix Vue, Headless UI) gèrent ARIA, focus, clavier. 2) Linter
eslint-plugin-vuejs-accessibility détecte les problèmes. 3) Tests E2E avec axe-core/pa11y. 4) Audit Lighthouse régulier.
Les composants "headless" sont essentiels : ils gèrent toute la logique d'accessibilité sans imposer de style. Vous gardez le contrôle du design.
Explication :
@vue/apollo-composable (Apollo) ou Villus (plus léger) fournissent des composables réactifs :
useQuery(), useMutation(). Le cache Apollo normalise les données et met à jour l'UI automatiquement.
Pour les applications simples, Villus est plus léger et plus facile à configurer. Pour des besoins avancés (cache normalisé, pagination), préférez Apollo.
Explication :
Sentry (plugin Vue) capture les erreurs avec le stack trace complet et le contexte Vue (props, state). Pour les Web Vitals (LCP, CLS, INP), on peut créer un composable
usePerformanceObserver() et envoyer les métriques à un service d'analytics.
Créez un wrapper autour de
app.config.errorHandler pour enrichir les erreurs avec le state Pinia et les infos de route avant de les envoyer à Sentry.
Explication :
Vapor Mode (en développement) est un nouveau mode de compilation qui élimine le Virtual DOM. Les templates sont compilés en fonctions de mise à jour DOM directes et ciblées (fine-grained reactivity). Objectif : performances proches de SolidJS/Svelte, tout en gardant l'API Vue existante.
Vapor Mode sera optionnel (par composant). Vous pourrez migrer progressivement sans réécrire toute l'application.