Vous avez un SPA React, votre INP en lab est à 120 ms, et pourtant la Search Console vous dit que l'expérience utilisateur est mauvaise. La donnée terrain ne ressemble pas à votre tableau Lighthouse. Et pour cause : depuis le passage de FID à INP le 12 mars 2024, toutes les interactions après le premier chargement sont mesurées, mais elles restent agrégées sous l'URL d'entrée. Une session de dix routes différentes dans votre app Vue ? Un seul score INP, attribué à la mauvaise page. C'est précisément ce que les Soft Navigations veulent corriger.
Le 20 avril 2026, Chrome for Developers a publié l'annonce du nouvel origin trial des Soft Navigations, ouvert à partir de Chrome 147 et qui court jusqu'à Chrome 149. Les mots exacts du blog : "A new, and hopefully final, Soft Navigations origin trial". Le "hopefully final" n'est pas anodin. C'est la quatrième tentative depuis 2022, et c'est la première qui ressemble à une vraie ligne d'arrivée. Sous le capot, l'API a changé en profondeur depuis le précédent OT de juillet 2025.
Le problème SPA en clair#
Reprenons à zéro pour les devs qui n'ont pas suivi la saga depuis Chrome 110. Côté navigateur, une "vraie" navigation, c'est un changement d'URL accompagné d'un rechargement complet de la page : on déclenche FCP, LCP, on remet à zéro les compteurs, le PerformanceObserver capture tout, CrUX collecte la donnée et l'attribue à la nouvelle URL. C'est le modèle MPA (multi-page application) classique. Tout marche.
Côté SPA, ce modèle s'effondre. Quand React Router ou Vue Router fait un history.pushState, l'URL change dans la barre, mais le navigateur ne considère pas que vous avez navigué. Aucun nouveau LCP, aucun reset INP. Salt.agency l'a résumé sans ambiguïté : avant l'API, "all SPA metrics were grouped under the entry point URL". L'app a beau être bien optimisée par route, vos rapports CrUX ne le voient pas. Stan Ventures a poussé le constat plus loin : l'INP devient "unreliable or completely missing" sur les SPA.
Le résultat concret pour le SEO, je le vois sur trois clients e-commerce qui tournent sur Next.js App Router : la page produit qui rame est invisible dans GSC parce qu'elle est rangée sous / ou sous la page catégorie d'entrée. Vous optimisez à l'aveugle. Les techniques générales pour redresser l'INP, je les ai détaillées dans Core Web Vitals : optimiser LCP, CLS et INP en 2026, mais aucune ne résout le problème d'agrégation décrit ici.
La timeline Chrome, version condensée#
L'API Soft Navigations n'est pas nouvelle. Elle traîne depuis 2022, et chaque révision a tué et reconstruit ses heuristiques. Le changelog Chromium est public, je l'ai recompilé pour les principales itérations.
- Chrome 110 (2022) : premier origin trial. Heuristique très basique : clic utilisateur + changement URL + ajout DOM = soft nav. NavigationId au format UUID, ID séquentiel entier ensuite.
- Chrome 117 (2023) : FP et FCP ne sont plus émis après une soft navigation. La séparation entre hard et soft commence à devenir nette.
- Chrome 119 (2023) : les événements clavier déclenchent désormais aussi des soft navigations. Avant, seulement les clics.
- Chrome 121 (2024) : le seuil de paint requis chute de 20 % à 2 % de la surface visible. Beaucoup plus de transitions SPA sont reconnues.
- Chrome 139 (31 juillet 2025) : refonte complète. Introduction de
InteractionContentfulPaint(ICP), NavigationId redevient un entier numérique, tracking paint indépendant par interaction. Un nouvel origin trial démarre. À cette date,replaceStaten'est PAS reconnu comme déclencheur. - Chrome 147 (avril 2026) : OT "hopefully final".
replaceStatedevient supporté (les devs l'avaient demandé), ICP est découplé des soft navigations pour devenir une métrique d'interaction utilisable seule,largestInteractionContentfulPaintest ajouté à l'entry. LestartTimed'uneSoftNavigationEntrycorrespond maintenant austartTimede l'interaction qui l'a déclenchée. Chrome 148 corrige un bug d'attribution NavigationId pour les entries ICP.
Quatre ans d'itérations pour stabiliser trois signaux. C'est long, et c'est révélateur : détecter qu'un utilisateur a "vraiment changé de page" dans un SPA est un problème heuristique tordu. Pas un bug à corriger, un design space à explorer.
Ce que dit la spec WICG#
Côté standard, la spec est publiée sur https://wicg.github.io/soft-navigations/, en statut Draft Community Group Report depuis le 16 avril 2026. La formulation officielle d'une soft navigation : "a same-document navigation satisfying: (1) a same-document URL change occurs while an InteractionContext is active, and (2) a contentful paint occurs attributed to that same context". Traduction dev : interaction utilisateur active + changement d'URL same-document + paint visible attribué au même contexte.
Trois signaux, ordre flexible, mais les trois doivent être présents dans la même fenêtre d'attribution. Si vous animez une transition CSS sans changer l'URL, ce n'est pas une soft nav. Si vous changez l'URL via history.pushState mais sans repeindre du contenu, ce n'est pas une soft nav. Si l'URL change suite à un timeout sans interaction utilisateur, idem.
Attention au statut : "This document is not a W3C Standards Track". C'est un draft de Community Group, pas une norme. Et c'est implémenté uniquement par Chromium. Firefox (Gecko) et Safari (WebKit) n'ont aucun chantier équivalent en cours. Firefox a ajouté l'INP en Firefox 144 (octobre 2025), mais c'est sur l'INP classique sans tracking par soft nav. Si vous comptez sur une convergence cross-browser pour planifier votre roadmap perf, vous allez attendre longtemps.
Le code minimal#
Pour s'amuser dès aujourd'hui, deux options. La première, propre pour la production de test : enregistrer son origine au programme d'origin trial Chrome et déposer le token dans le <head>. La seconde, locale : activer le flag chrome://flags/#soft-navigation-heuristics.
Une fois actif, la détection feature se fait simplement :
const supported = PerformanceObserver.supportedEntryTypes.includes('soft-navigation')
Et l'observation des soft navs :
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
console.log('Soft nav:', entry.name, 'navId:', entry.navigationId)
console.log('Type:', entry.navigationType, 'startTime:', entry.startTime)
}
})
observer.observe({ type: 'soft-navigation', buffered: true })
Les champs disponibles sur SoftNavigationEntry : name (la nouvelle URL), navigationId (entier numérique depuis Chrome 139), startTime (= startTime de l'interaction déclencheuse depuis Chrome 147), navigationType (push ou replace). Côté INP, Chrome reset la métrique à chaque soft nav et la mesure séparément dans la fenêtre suivante. Vos rapports gagnent un niveau de granularité que vous n'aviez pas avant.
Pour la stack web-vitals.js, c'est un peu plus tordu. Le support soft nav vit dans une branche dédiée nommée soft-navs, pas dans la version stable. Installation : npm i web-vitals@soft-navs. Le package.json côté DebugBear donne "web-vitals": "^3.5.0-soft-navs-10". Vous activez l'option à l'appel des handlers : onINP(reporter, { reportSoftNavs: true }). Idem pour onCLS et onLCP. FCP et FID ne sont pas supportés en soft nav. C'est volontaire : FCP n'a pas de sens en soft nav (la page n'est jamais peinte from scratch), et FID est mort.
Le gros caveat : CrUX ne mesure rien#
Et c'est là que je freine l'enthousiasme général. La page blog Chrome 147 le dit noir sur blanc : "This origin trial is to evaluate the new API and not how this data will be used in CrUX or tooling. That will be decided after we're satisfied with the API." DebugBear renchérit : "Google has no known plans to add the impact of soft navigations to the CrUX report".
Concrètement, ça veut dire que même si vous activez l'OT, que vos soft navs sont parfaitement trackées dans votre RUM custom et que votre INP par route est nickel, le Chrome User Experience Report continue d'agréger vos interactions SPA sous l'URL d'entrée. Search Console aussi. Le signal de classement Google n'a pas bougé. Pour 2026, c'est une amélioration de votre observabilité interne, pas une amélioration de votre Core Web Vitals 2026 et impact SEO.
J'ai un doute sur le timing réel d'intégration CrUX. Le blog Chrome dit que Google vise un shipping "later this year" (2026) après l'OT, mais l'intégration CrUX sera décidée séparément. Honnêtement, je vois bien Google traîner encore six à douze mois après le shipping pour caler les pondérations. Les taux de réussite CWV desktop ont atteint 57,1 % en octobre 2025 selon DebugBear, 49,7 % côté mobile. Ajouter brutalement les soft navs au calcul ferait probablement chuter ces taux de plusieurs points. Google n'aime pas casser ses propres métriques.
Ce que ça change pour Next.js, Vue et React Router#
Question pratique : qu'est-ce que vos frameworks supportent aujourd'hui ? Côté Next.js, l'App Router fait déjà de la client-side navigation native via le composant <Link> et préserve les layouts. C'est une soft navigation au sens utilisateur. Mais l'intégration officielle dans useReportWebVitals n'est pas livrée. L'issue GitHub vercel/next.js#45557 est fermée sans engagement d'ETA de la team. Pour l'instant, vous instrumentez à la main avec web-vitals@soft-navs dans un client component.
Vue Router 4 est dans la même situation. Le plugin vue-web-vitals de NuroDev existe sur GitHub, encore marqué WIP, et il faut le brancher manuellement. Pas d'intégration officielle Vue ou Nuxt à ma connaissance, et je ne vois rien dans la roadmap publique de l'équipe.
Pour les autres stacks (Angular, Svelte Kit, Solid Router), le pattern est le même : votre router émet déjà des events au changement de route, vous pouvez soit vous brancher dessus, soit utiliser le PerformanceObserver natif quand l'OT est actif. Attention à la dédup : combiner un listener router et un observer soft-nav, c'est s'exposer au double comptage des pageviews. Choisissez une seule source de vérité.
Pour le contexte SEO global de vitesse de chargement et impact SEO, considérez que l'OT 2026 est un outil de diagnostic, pas un signal de classement.
Mon verdict de dev#
Pour les fans du sous le capot : oui, activez l'OT sur un environnement de staging et instrumentez avec web-vitals@soft-navs. Vous allez découvrir des choses que vos rapports CrUX vous cachaient depuis deux ans. La granularité par route va remonter des INP outliers qui dormaient agrégés. C'est précieux pour prioriser les chantiers perf.
Pour les pragmatiques côté SEO : ne refondez pas votre stack de monitoring autour de cette API. Tant que CrUX ne consomme pas la donnée, votre Search Console et votre ranking n'en sauront rien. Continuez à optimiser comme avant, en sachant que la prochaine étape (1-2 ans probablement) sera un CrUX granulaire par soft nav, et que ce jour-là, les SPA qui ne tiendront pas 200 ms d'INP par route vont morfler. Préparez le terrain, ne précipitez pas.
Une dernière nuance honnête : je sais pas exactement quand Google va flipper le switch côté CrUX. Le pattern "API stable, donnée pas exposée" peut durer. Cf. IndexNow, qui tourne depuis 2021 sans que Google bouge le petit doigt. La différence ici, c'est que c'est Chrome qui pousse pour Chrome. La pression interne est plus forte. Mais pari côté délai : je miserais sur 2027 pour une intégration CrUX, pas avant.
À vous de jouer : activez le flag, observez vos soft navs, mesurez votre INP par route. La prochaine version stable arrive vite.
Sources#
- Chrome for Developers, Final Soft Navigations Origin Trial (20 avril 2026)
- Chrome for Developers, Soft Navigations Experiment Documentation
- WICG Soft Navigations Draft (16 avril 2026)
- Chromium Speed Changelog, Soft Navigations
- Chrome for Developers, New Soft Navigations Origin Trial (juillet 2025)
- web.dev, Interaction to Next Paint (INP)
- DebugBear, Soft Navigations Guide
- DebugBear, React Soft Navigations Tutorial
- DebugBear, 2025 in Web Performance
- Salt Agency, Why the Soft Navigations API Enables Better SPA CWV Auditing
- Stan Ventures, Chrome 139 Rolls Out Soft Navigations API





