Le mode History de Vue Router permet de construire des applications SPA avec des URL propres et sémantiques, éliminant le symbole #. Sa mise en œuvre efficace nécessite une compréhension approfondie de ses mécanismes et une configuration minutieuse tant côté client que serveur.
Fondamentaux du mode History
Contrairement au mode hash qui utilise window.onhashchange, le mode History repose sur l'API HTML5 History (pushState / replaceState) et l'événement popstate. Cela offre des URL plus naturelles et de meilleures possibilités pour le SEO, mais exige une collaboration étroite avec la configuration du serveur.
Voici comment initialiser un routeur en mode History avec Vue 3 :
// Fichier : src/router/index.js
import { createRouter, createWebHistory } from 'vue-router'
import VueAccueil from '@/views/VueAccueil.vue'
const definitionRoutes = [
{ path: '/', component: VueAccueil },
{ path: '/a-propos', component: () => import('@/views/VueAPropos.vue') }
]
const instanceRouter = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: definitionRoutes
})
export default instanceRouter
Configuration impérative du serveur
Puisque toutes les routes sont gérées par le client, le serveur doit rediriger toute requête ne correspondant pas à un fichier statique vers le point d'entrée index.html. L'absence de cette configuration entraîne une erreur 404 lors de l'accès direct à une route ou du rafraîchissement de la page.
| Serveur | Configuraton essentielle |
|---|---|
| Nginx | Utiliser la directive try_files $uri $uri/ /index.html; dans le bloc location racine. |
| Apache | Créer un fichier .htaccess avec les règles de réécriture pour rediriger vers index.html. |
| Node.js (Exppress) | Placer le middleware de fallback (app.get('*', ...)) APRÈS la déclaration des routes API et des fichiers statiques. |
En développement, les outils comme Vite ou Vue CLI gèrent ce point automatiquement. C'est en déploiement de production que cette configuration devient cruciale.
Optimisation des performances : le chargement asynchrone des composants
Pour réduire la taille du bundle initial, il est fortement conseillé de découper le code par route. Cela se fait en important dynamiquement les composants via la syntaxe () => import(), ce qui génère des chunks séparés.
const routes = [
{
path: '/tableau-de-bord',
name: 'TableauDeBord',
component: () => import(
/* webpackChunkName: "tableau-de-bord" */
'@/views/TableauDeBord.vue'
)
}
]
Cette stratégie, combinée à une configuration serveur correcte, garantit à la fois des performances initiales optimales et une expérience utilisateur fluide sans rechargement de page.
Gestion des paramètres d'URL dynamiques et de requête
Le mode History ne change pas la manière dont Vue Router capture les segments dynamiques de l'URL et les paramètres de requête. Ces valeurs restent accessibles via les propriétés $route.params et $route.query respectivement, et sont préservées lors des navigations internes.
Configuration avancée : comportement de défilement et navigation programmatique
Pour une expérience utilisateur soignée, le comportement de défilement lors des changements de route doit être contrôlé. La propriété scrollBehavior du routeur permet de restaurer la position précédente lors d'un retour arrière ou de remonter en haut de page pour une nouvelle navigation.
const configurationRouteur = {
scrollBehavior(positionDestination, positionSource, positionSauvegardee) {
// Restaure la position sauvegardée par le navigateur (navigation arrière/avant)
if (positionSauvegardee) {
return positionSauvegardee
}
// Sinon, défile en haut de la page avec un effet de lissage
return { top: 0, behavior: 'smooth' }
}
}
La navigation programmatique utilise router.push() ou router.replace() pour déclencher des transitions de route depuis le code, offrant un contrôle complet sur le flux applicaitf.
Pièges courants en environnement de production
404 au rafraîchissement : C'est le signe d'une configuration serveur manquante ou incorrecte. Vérifiez que le serveur renvoie toujours index.html pour les chemins non statiques.
Routes imbriquées complexes : Une imbrication excessive (au-delà de 3 niveaux) peut rendre le débogage difficile. Préférez une structure de routes plus plate et utilisez des redirections ou des vues nommées pour organiser l'interface.
Déploiement dans un sous-dossier : Lorsque l'application n'est pas servie depuis la racine du domaine, l'attribut base de l'historique du routeur doit être configuré pour refléter ce chemin, de même que le publicPath dans la configuration du bundler (Webpack/Vite).
// Pour une application accessible à https://example.com/mon-app/
const instanceRouter = createRouter({
history: createWebHistory('/mon-app/'), // Correspond au publicPath
routes: definitionRoutes
})
Considérations pour la fiabilité en production
Pour une application robuste, intégrez une surveillance proactive des erreurs JavaScript non gérées. Une capture globale avec rapport d'erreur permet d'identifier rapidement les problèmes survenant chez les utilisateurs.
window.addEventListener('erreurNonGeree', (evenement) => {
const donneesRapport = {
message: evenement.message,
scriptSource: evenement.filename,
ligne: evenement.lineno,
colonne: evenement.colno,
pileAppels: evenement.error?.stack
};
navigator.sendBeacon('/api/rapport-erreur', JSON.stringify(donneesRapport));
});
Cette approche, combinée à une bonne gestion du code asynchrone et à des tests de santé automatisés, est fondamentale pour maintenir une haute disponibilité de l'application.