Shallow Routing : Naviguer vite et bien sans recharger la page
Le shallow routing permet de changer d'URL sans perdre l'état de l'interface, pour des expériences plus rapides, plus fluides, et plus SEO-friendly. Dans cet article, on explore ce concept en profondeur, ses pièges, ses cas d’usage...
Dans un web toujours plus interactif, les utilisateurs attendent des applications rapides, réactives et sans friction. Quand on change d'onglet, filtre un tableau ou ouvre une modale, l'expérience ne devrait pas se dégrader, ni provoquer un flash d'attente ou une perte d'état.
C'est dans ce contexte que le shallow routing s'impose comme un outil précieux. Encore méconnu, il permet de changer d'URL sans recharger la page, tout en conservant l'état de l'interface. Un détail ? Pas vraiment. Bien utilisé, c'est un levier de performance, d'UX et même de SEO technique.
Qu'est-ce que le shallow routing ?
Le shallow routing consiste à modifier l'URL visible dans la barre d'adresse du navigateur sans recharger la page ni relancer la logique de chargement globale de l'application.
Concrètement, cela s'appuie sur les méthodes history.pushState()
ou history.replaceState()
du navigateur. Cela permet d'indiquer une nouvelle URL au navigateur, sans déclencher une requête réseau ni détruire la structure actuelle de la page.
Cela s'oppose au routing classique, où chaque changement d'URL déclenche généralement un nouveau rendu complet de la page, voire une nouvelle requête vers le serveur.
Différence de comportement
Pourquoi utiliser le shallow routing ?
Voici les bénéfices clés du shallow routing, tant pour les développeurs que pour les profils orientés UX ou marketing technique.
- Des performances accrues : En évitant les appels réseau ou les rechargements d'interface inutiles, le shallow routing rend l'interaction quasi-instantanée.
- Une meilleure expérience utilisateur : Pas d'écran blanc, pas d'interruption de scroll ou de formulaire : la navigation semble naturelle, sans rupture.
- Des URLs dynamiques et partageables : Le shallow routing permet d'exprimer l'état de l'application dans l'URL (
?tab=profil
,?photo=42
...), sans pour autant déclencher de rerender. Idéal pour le tracking, le partage de lien, ou la navigation entre onglets ou vues modales. - Une gestion fine de l'état : Plutôt que de stocker l'état de l'interface uniquement en mémoire, on peut le refléter dans l'URL. Cela permet notamment de synchroniser les filtres, le tri, ou même une modale ouverte.
À lire aussi :
- Infinite scroll, pagination & SEO : comment les combiner sans tuer votre trafic ?
- Lazyloading en 2025 : vous chargez léger ou vous chargez mal ?
- Cache web : le guide pour ne plus jamais dire "ça marche chez moi"
Les pièges fréquents à éviter
Même si le shallow routing est puissant, il demande un minimum de rigueur côté développement.
- Gestion explicite du bouton "Retour" et "Suivant" : Puisque vous manipulez manuellement l'historique, il faut penser à écouter les événements popstate et enregistrer un state clair dans pushState. Sinon, impossible de savoir si on était dans une modale ou sur une page complète après retour ou avancée.
- Synchronisation manuelle de l'interface : Changer l'URL n'est qu'une partie du travail. Vos composants doivent se mettre à jour en fonction des nouveaux paramètres. Il ne faut pas compter sur un framework ou un rafraîchissement implicite pour le faire à votre place.
Exemple complet : galerie photo avec modale
Prenons un exemple inspiré de Facebook : une galerie photo. Vous pouvez cliquer sur une image pour l'agrandir en modale sans quitter la page. Mais si vous copiez-collez l'URL, la personne qui ouvre ce lien voit la photo en pleine page, avec tout le contexte chargé normalement.
Ce pattern hybride est à la fois UX-friendly et SEO-compatible.
HTML : un lien fonctionnel sans JavaScript
<a href="/photo/42" class="photo-link" data-photo-id="42">
<img src="/img/thumbs/42.jpg" alt="Photo 42" />
</a>
Sans JavaScript, ce lien fonctionne parfaitement : il mène à une page /photo/42
avec un rendu serveur complet.
Avec JavaScript, on peut intercepter le clic pour afficher une modale et éviter la navigation complète.
JavaScript : shallow routing avec récupération de contenu réel
document.querySelectorAll('.photo-link').forEach(link => {
link.addEventListener('click', async (e) => {
// Bloquage du lien naturel
e.preventDefault();
const photoId = link.dataset.photoId;
const url = `/photo/${photoId}`;
// Mise à jour de l'URL + état
history.pushState({ modal: true, photoId }, '', url);
// Appel de la vraie page, mais via JS
const response = await fetch(url);
if (response.ok) {
const html = await response.text();
openPhotoModal(html);
}
});
});
function openPhotoModal(innerHtml) {
const modal = document.createElement('div');
modal.className = 'modal';
modal.innerHTML = `
<div class="modal-content">
${innerHtml}
<button id="close-modal">Fermer</button>
</div>
`;
document.body.appendChild(modal);
document.getElementById('close-modal').addEventListener('click', () => {
modal.remove();
history.back();
});
}
// Gérer les boutons Précédent / Suivant
window.addEventListener('popstate', async (event) => {
const state = event.state || {};
if (state.modal && state.photoId) {
const response = await fetch(`/photo/${state.photoId}`);
const html = await response.text();
openPhotoModal(html);
} else {
const modal = document.querySelector('.modal');
if (modal) modal.remove();
}
});
Et côté serveur ?
Vous pouvez détecter côté serveur si la requête provient de JavaScript en observant les headers comme Accept, Sec-Fetch-Mode ou d'autres signaux modernes. Cela vous permet de renvoyer une version réduite de la page (par exemple, uniquement le HTML de la modale) lors d'un fetch().
Si une même URL (/photo/42
) peut renvoyer deux contenus différents (modale vs page complète), n'oubliez pas d'ajouter un header Vary
, comme :
Vary: Accept, Sec-Fetch-Mode
Cela évite que les systèmes de cache retournent un contenu inadéquat à un autre type de requête.
Bonnes pratiques
Le shallow routing, bien utilisé, est un véritable levier de performance, d'UX et de compatibilité SEO. Il vous permet d'enrichir l'interface sans compromettre sa lisibilité, son accessibilité ni sa structure de navigation.
À retenir :
- Utilisez-le pour les interactions dynamiques (modales, filtres, onglets...)
- Gardez l'URL synchronisée avec l'état de l'interface
- Pensez aux cas sans JavaScript : le lien doit fonctionner seul
- Enregistrez un state explicite pour gérer retour/suivant
- Vous pouvez appeler vos vraies pages avec un header ou détection automatique pour en extraire une version modale
- Ne remplacez pas le routing classique : complétez-le intelligemment
Le shallow routing n'est pas là pour contourner les bonnes pratiques, il est là pour les enrichir, avec plus de finesse et plus de fluidité.
Vous travaillez sur une interface dynamique ou un site à fort enjeu SEO ? Enodo vous accompagne pour allier performance, accessibilité et impact.