bfcache en 2026 : accélérer le retour sans surcoder
Le bfcache rend le retour arrière quasi instantané. Identifiez les blocages, mesurez son effet et corrigez votre site sans refonte lourde.
Le bouton Retour fait partie des interactions les plus fréquentes sur le Web : revenir à une liste après avoir consulté une fiche produit, retourner à des résultats de recherche, corriger un formulaire ou reprendre une comparaison. Pourtant, beaucoup de sites traitent ce parcours comme une navigation ordinaire et relancent une requête réseau, le rendu de la page et les scripts.
Le back/forward cache, généralement abrégé bfcache, évite ce travail lorsqu’il est disponible. Le navigateur conserve alors un instantané vivant de la page précédente et peut le restaurer lors d’une navigation arrière ou avant. Pour l’utilisateur, le retour peut paraître immédiat, y compris lorsque le réseau est lent ou instable.
Ce mécanisme ne demande ni bibliothèque JavaScript, ni refonte en SPA, ni préchargement généralisé. Il repose surtout sur une idée simple : ne pas empêcher le navigateur de garder une page en mémoire lorsqu’elle n’est plus visible. Voici comment comprendre le bfcache, identifier les blocages et corriger les problèmes sans ajouter de complexité inutile.
Le bfcache : ce que le navigateur restaure réellement
Le bfcache n’est pas le cache HTTP. Le cache HTTP stocke des ressources ou des réponses, selon leurs en-têtes : documents HTML, feuilles CSS, scripts, images ou données d’API. Lorsqu’une page est revisitée, le navigateur peut tout de même devoir reconstruire le document, réexécuter du JavaScript et produire l’interface.
Avec le back/forward cache, le navigateur garde une page entière dans un état suspendu. Cela peut inclure le DOM, l’état JavaScript, la position de défilement, les champs déjà remplis et l’état visuel de l’interface. En revenant à cette page, il ne s’agit donc pas nécessairement de la télécharger ou de l’initialiser une seconde fois : le navigateur la remet au premier plan.
Cette distinction a des conséquences pratiques importantes :
- une bonne politique de cache HTTP reste utile, mais ne garantit pas une restauration depuis le bfcache ;
- un site rendu côté serveur peut bénéficier du bfcache autant qu’une application JavaScript ;
- une page très riche peut revenir vite si elle reste éligible ;
- un script qui suppose qu’une page est toujours recréée doit aussi savoir gérer une reprise.
Lorsqu’un document quitte l’écran, le navigateur peut le suspendre plutôt que le détruire. Lorsqu’il revient, l’événement pageshow est déclenché. Sa propriété persisted indique si la page a été restaurée depuis le bfcache. De même, l’événement pagehide fournit une information utile avant la mise en cache potentielle.
Le navigateur garde néanmoins la décision finale. La mémoire disponible, le comportement de la page, les politiques de sécurité et l’implémentation propre à chaque navigateur peuvent influer sur l’éligibilité. Il faut donc considérer le bfcache comme une optimisation opportuniste à favoriser, pas comme une promesse applicative sur laquelle fonder une fonction métier critique.
Pourquoi le retour arrière mérite une vraie attention performance
Les indicateurs de chargement classiques observent souvent une arrivée initiale : ouverture d’une URL, chargement d’un document, rendu principal, interaction. Or, un utilisateur ne suit pas toujours un parcours linéaire. Il ouvre un article, revient à la page de catégorie, consulte un autre résultat, puis avance à nouveau. Si chaque retour redémarre la page, le site répète un travail déjà accompli.
Le bfcache améliore particulièrement les parcours à forte exploration :
- catalogues e-commerce et pages de recherche ;
- listes d’articles, archives et tags ;
- annonces, offres d’emploi ou comparateurs ;
- documentations techniques avec beaucoup de pages liées ;
- interfaces de back-office où l’on alterne entre liste et détail.
Il complète les optimisations abordées dans un travail sur les temps de chargement d’un site moderne. Réduire le JavaScript, optimiser les images et limiter les requêtes restent essentiels pour une première visite. Le bfcache, lui, traite un autre moment du parcours : la réapparition d’une page que l’utilisateur vient juste de quitter.
Il offre aussi un avantage de robustesse. Une restauration depuis le bfcache ne dépend pas forcément d’une nouvelle réponse serveur ni d’un réseau disponible au moment du retour. Ce n’est pas une alternative au mode hors ligne, mais c’est une façon très concrète d’éviter des chargements inutiles.
Les causes courantes qui empêchent la mise en bfcache
Les raisons de non-éligibilité ne sont pas parfaitement identiques entre Chrome, Firefox et Safari. Un comportement qui passe dans un navigateur peut être refusé dans un autre. La bonne méthode n’est donc pas d’appliquer une liste de recettes à l’aveugle : il faut d’abord regarder le diagnostic fourni pour la page et le navigateur concernés.
L’événement unload reste un mauvais candidat
L’usage de l’événement unload est une cause classique de difficulté. Historiquement, il était utilisé pour envoyer des données d’analytics, fermer une connexion ou nettoyer une ressource à la sortie d’une page. Mais il est peu fiable, peut dégrader l’expérience de navigation et nuit à la compatibilité avec le bfcache.
Évitez d’ajouter un gestionnaire unload dans votre code applicatif, dans un gestionnaire de tags ou dans un script tiers. Songez aussi aux dépendances anciennes : le script responsable n’est pas toujours dans votre dépôt principal. Une solution de consentement, un outil de mesure ou un widget embarqué peut enregistrer cet événement à votre insu.
Pour envoyer une information légère à la fin d’une session de visibilité, l’API navigator.sendBeacon() ou l’option keepalive de fetch() peuvent être plus adaptées selon le besoin. Elles ne remplacent pas une conception correcte de la mesure, mais évitent de dépendre du cycle de destruction de la page.
Les confirmations beforeunload doivent rester exceptionnelles
beforeunload répond à un autre besoin : avertir un utilisateur qui risque de perdre des modifications non enregistrées. Cet événement ne doit pas devenir un réflexe global sur toutes les pages. Son impact sur le bfcache varie selon les navigateurs et leurs versions ; Firefox, notamment, ne met pas en bfcache les pages utilisant beforeunload.
Le compromis pragmatique consiste à n’ajouter ce comportement que lorsqu’un formulaire est réellement modifié, puis à retirer l’écouteur dès que les données sont enregistrées ou que l’état redevient propre. Une page de lecture, une fiche produit ou un écran sans édition ne devrait pas installer cette protection par défaut.
Les API et états actifs à vérifier
Certains états vivants peuvent empêcher ou compliquer une suspension : connexions temps réel, transactions en cours, verrous, accès matériel ou intégrations externes. Les effets dépendent de l’API et du navigateur. Une connexion WebSocket, par exemple, mérite une vérification explicite dans vos navigateurs cibles plutôt qu’une supposition.
Le même principe s’applique aux iframes tierces, aux lecteurs vidéo, à l’accès à la caméra ou au micro, et aux pages qui manipulent des ressources partagées. Le diagnostic du navigateur indiquera parfois que le blocage vient d’un sous-cadre et non du document principal. Dans ce cas, modifier votre seul code de page ne suffira pas toujours.
Les réponses HTTP et les pages sensibles
Les en-têtes HTTP peuvent aussi jouer un rôle. Les navigateurs protègent particulièrement les documents contenant des données sensibles et les réponses qui indiquent explicitement de ne pas être stockées. Les règles évoluent, notamment autour de Cache-Control: no-store, et ne sont pas uniformes. Il serait donc imprudent de retirer cet en-tête uniquement pour obtenir du bfcache.
La sécurité et la confidentialité passent avant un gain de navigation. Sur un compte bancaire, une zone médicale ou une interface contenant des informations personnelles, la stratégie de cache doit être validée selon les contraintes du produit et de la sécurité. L’outil de diagnostic permet de constater l’effet d’une décision ; il ne doit pas pousser à contourner une exigence légitime.
Mesurer l’éligibilité avec les outils navigateur
Commencez par un parcours précis. Par exemple : ouvrez une page de résultats, visitez une fiche, puis utilisez le bouton Retour du navigateur. Répétez le test en navigation privée ou avec un profil propre afin de réduire l’influence des extensions et de l’état de session.
Dans Chrome DevTools, le panneau Application comporte une section dédiée au Back/forward cache. Elle permet de tester la restauration d’une page et affiche les raisons pour lesquelles elle n’a pas été restaurée. Le rapport distingue les causes exploitables et les causes qui peuvent dépendre d’autres conditions. C’est le meilleur point de départ : une raison concrète vaut mieux qu’une longue liste de suspicions.
Chrome expose également des informations de non-restauration via PerformanceNavigationTiming et la propriété notRestoredReasons, lorsque le navigateur la prend en charge. Cette API peut aider à enrichir une analyse interne ou un outil de suivi, mais elle ne doit pas devenir un prérequis pour votre site : sa disponibilité varie selon les navigateurs.
Pour vérifier une restauration dans le code, écoutez pageshow et observez event.persisted. Une instrumentation minimale peut journaliser cette valeur dans votre environnement de test. En production, vous pouvez aussi transmettre un événement analytique spécifique, à condition de respecter votre politique de consentement et de ne pas gonfler artificiellement vos pages vues.
La documentation de web.dev sur le bfcache et la référence MDN sont utiles pour approfondir les comportements et les événements associés. Gardez toutefois votre test de parcours comme source de vérité : le résultat dépend de la page réellement livrée, de ses scripts tiers et du navigateur utilisé.
Mesurer l’impact dans les parcours réels
Un taux global de restauration est intéressant, mais il ne dit pas forcément où agir. Segmentez l’observation par type de parcours : liste vers détail, recherche vers contenu, tunnel d’inscription, documentation, espace connecté. Une page rarement revisitée n’a pas le même potentiel qu’une liste à laquelle les utilisateurs reviennent continuellement.
Une mesure utile peut associer :
- l’URL ou le type de page restauré ;
- la présence de event.persisted lors de pageshow ;
- le navigateur, dans le respect de votre modèle de données ;
- le parcours précédent lorsque cette information est déjà disponible ;
- les erreurs JavaScript ou incohérences observées après une reprise.
Ne confondez pas bfcache et performance de première visite. Une navigation restaurée ne produit pas les mêmes signaux qu’un nouveau chargement. Dans vos tableaux de bord, identifiez clairement les restaurations afin de ne pas mélanger leurs durées avec celles des chargements réseau. Cette séparation complète utilement le suivi des Web Vitals et de l’INP.
Enfin, testez le comportement fonctionnel, pas seulement le statut “restored”. Après un retour arrière, un compteur, une bannière de consentement, un état de panier, une session expirée ou une donnée affichée dynamiquement peuvent nécessiter une synchronisation. Le bfcache accélère la reprise ; votre interface doit encore montrer un état cohérent.
Corriger sans casser les scripts ni surarchitecturer
La correction la plus rentable est souvent la suppression d’un comportement inutile. Cherchez d’abord les écouteurs unload et beforeunload dans le code, les bundles générés et les scripts chargés par votre gestionnaire de balises. Remplacez-les uniquement lorsque leur objectif est compris.
Pour une page avec formulaire, adoptez une logique explicite d’état modifié :
- n’installez beforeunload qu’après une modification utilisateur significative ;
- retirez-le après une sauvegarde confirmée ;
- préservez les brouillons côté serveur ou local lorsque cela est pertinent ;
- ne comptez pas sur la boîte de dialogue du navigateur comme unique protection contre la perte de données.
Pour le cycle de vie, préférez visibilitychange afin de détecter qu’un document devient caché, et utilisez pagehide ou pageshow pour les cas où l’état de navigation compte réellement. Il ne s’agit pas d’empiler les événements : définissez pour chacun une responsabilité claire.
Par exemple, une interface qui affiche des données potentiellement périmées peut, au retour depuis le bfcache, demander une vérification légère à son API. Elle ne doit pas forcément reconstruire toute l’application ni vider son DOM. Si les données n’ont pas changé, l’utilisateur garde le bénéfice de la restauration. Si elles ont changé, l’interface met à jour seulement les éléments concernés.
Le bon objectif n’est pas de forcer une page à entrer dans le bfcache. C’est de retirer les effets de bord inutiles qui empêchent le navigateur de faire son travail.
Éviter les pièges dans les applications JavaScript
Les applications client ont parfois été conçues autour d’un seul événement : le chargement initial. Elles exécutent des initialisations au démarrage, créent des abonnements, ouvrent des connexions et supposent qu’une navigation signifie une destruction complète. Le bfcache remet en cause cette hypothèse, mais ne réclame pas nécessairement une nouvelle architecture.
Auditez les fonctions d’initialisation. Si elles sont rappelées lors d’un pageshow, sont-elles idempotentes ? Créent-elles un second écouteur sur le même bouton ? Démarrent-elles deux minuteurs ? Envoient-elles un événement de mesure en double ? Une initialisation idempotente donne le même résultat même lorsqu’elle est exécutée plusieurs fois ; c’est une propriété précieuse au-delà du seul bfcache.
Pour les scripts chargés de façon progressive, gardez les responsabilités localisées. Une fonctionnalité d’autocomplétion, un menu ou une modale n’a pas besoin d’un routeur global pour être compatible avec une restauration. Cette approche rejoint l’idée de JavaScript optionnel : utiliser du code client là où il apporte une interaction réelle, pas pour recréer un cycle de navigation que le navigateur sait déjà optimiser.
Les frameworks ne dispensent pas de cette vérification. Qu’une page soit construite avec React, Vue, Svelte, Astro ou du JavaScript natif, les scripts tiers et les écouteurs globaux peuvent décider de son éligibilité. Testez le HTML effectivement envoyé et le comportement de production, pas uniquement le code composant.
Une méthode de priorisation simple pour votre équipe
Le bfcache peut rester un sujet très opérationnel. Inutile de créer un chantier transverse avant d’avoir constaté un problème concret. Une séquence courte suffit généralement :
- choisissez trois à cinq parcours où le bouton Retour est naturel ;
- testez-les dans les navigateurs réellement utilisés par votre audience ;
- relevez les raisons de non-restauration dans les outils de développement ;
- classez les causes entre code interne, scripts tiers et contraintes de sécurité ;
- corrigez d’abord les écouteurs inutiles et les effets de bord faciles à isoler ;
- retestez le parcours complet, y compris l’état fonctionnel après restauration ;
- ajoutez ensuite une mesure légère en production si le volume et l’enjeu le justifient.
Documentez aussi les exceptions assumées. Une page peut avoir une raison valable de ne pas utiliser le bfcache. Le problème n’est pas l’exception elle-même, mais une exception invisible, héritée d’un ancien script et jamais réévaluée.
Conclusion : laissez le navigateur accélérer les retours
Le bfcache est un levier de performance discret, mais directement perceptible dans les parcours réels. Il ne remplace pas l’optimisation du serveur, du poids des pages ou des interactions. Il évite simplement de refaire un travail dont le navigateur possède déjà le résultat.
Commencez par tester un parcours liste-détail-retour dans DevTools, puis cherchez les raisons concrètes de non-restauration. Dans de nombreux cas, supprimer un écouteur unload, limiter beforeunload aux formulaires réellement modifiés ou corriger une initialisation de script suffit à améliorer l’expérience sans ajouter une couche JavaScript de plus.