Résumé

  • Le projet HTML 5 du W3C d’avril 2009 décrivait pushState() ajoutant une entrée d’état et popstate au retour vers une entrée enregistrée. L’historique du navigateur pouvait suivre plusieurs vues d’un même document.
  • La recommandation HTML5 de 2014 présentait replaceState() aux côtés de pushState() et un petit jeu qui redessinait son écran depuis event.state après Retour. Le navigateur conservait le billet; la page remontait le décor.

Le bouton Retour avait rempli son contrat. Il avait rejoint l’entrée précédente. Sur scène, pourtant, la page portait toujours le costume de la scène suivante. Le public déclarait le bouton cassé. Le navigateur avait le bon billet; le site avait perdu le décor correspondant.

À mesure que les sites ont commencé à remplacer des parties d’une page sans demander un nouveau document à chaque geste, ce décalage est devenu visible. Une galerie passait d’une image à l’autre. Une recherche montrait de nouveaux résultats. Une carte changeait de quartier. L’adresse pouvait rester la même pendant que l’écran bougeait. Puis le lecteur appuyait sur Retour pour revoir l’image, les résultats ou le lieu précédent. Sans entrée d’historique pour cette étape, le navigateur le ramenait ailleurs. Il fallait rapprocher la mémoire du navigateur de celle de l’application.

Le projet HTML 5 du W3C daté du 23 avril 2009 décrivait cette rencontre. Son interface History comprenait les commandes back, forward et go. pushState(data, title, url) ajoutait une entrée portant un état dans l’historique de la session, et un événement popstate accompagnait l’activation d’une entrée d’état. Une page pouvait donner une adresse et des données à l’une de ses vues tout en restant dans le même document. Le navigateur gagnait ainsi un chemin à travers les changements internes.

Le projet utilisait notamment l’idée d’un jeu dont la position pouvait être mise dans une adresse à conserver. Le joueur avance; la page dessine une nouvelle position; l’adresse et l’entrée d’historique peuvent avancer avec lui. Au retour, le navigateur retrouve l’état conservé. Le jeu doit tracer l’ancienne position. Le navigateur ne reconstruit pas tout seul le plateau simplement parce qu’il a gardé le billet de la partie.

La différence entre ajouter et remplacer une étape compte. Dans la recommandation HTML5 du W3C du 28 octobre 2014, pushState() ajoute une entrée tandis que replaceState() modifie l’entrée en cours. Une nouvelle vue que le lecteur voudra peut-être retrouver mérite une étape. Une correction de l’écran actuel peut rester au même endroit. Le site décide ainsi de la longueur du chemin Retour. Faire de chaque frappe une nouvelle étape transforme le bouton en exercice d’endurance; ignorer tous les changements de vue le fait sauter par-dessus le travail du lecteur.

Le texte de 2014 donne un exemple remarquablement simple : un jeu sur une ligne. Quand la position change, le code appelle history.pushState(...). Lorsqu’un événement popstate arrive, sa fonction onpopstate appelle setupPage(event.state) pour reconstruire l’affichage. Ces quelques lignes montrent la séparation complète des rôles. Le navigateur choisit la bonne entrée, l’application réinstalle la scène. Une adresse correcte au-dessus d’un écran erroné ressemble à une affiche de théâtre collée sur la mauvaise porte.

Le site ne pouvait pas écrire n’importe quelle adresse. La recommandation de 2014 imposait des vérifications sur l’URL associée au document. Le chapitre actuel du standard HTML vivant de WHATWG consacré à la navigation et à l’historique conserve une frontière précise pour la réécriture d’URL. Sur HTTP ou HTTPS, le chemin, les paramètres et le fragment peuvent varier dans le cadre permis; un site ne peut pas se déguiser en autre hôte par un simple appel à pushState(). L’adresse peut suivre la vue sans devenir une fausse enseigne.

Les données d’état forment un contrat entre deux métiers. Le navigateur les garde avec l’entrée. L’application décide ce qu’elles signifient : onglet choisi, position d’une carte, identifiant d’un élément. Au retour, popstate remet cette indication à la page. Si la page ne réagit pas, la barre d’adresse et l’écran racontent deux histoires différentes. Le registre du navigateur fonctionne; le machiniste n’a pas entendu son signal.

L’API ne confiait pas pour autant les commandes Retour et Avancer au site. Le lecteur les actionne et le navigateur parcourt toujours l’historique de session. Le site choisit à quel moment l’une de ses vues mérite une entrée, quelles données joindre à cette entrée et comment redessiner la vue quand elle redevient active. C’est cette petite coopération qui a rendu possible une navigation familière au sein d’une page changeante.

Le projet de 2009 et la recommandation de 2014 marquent deux moments de ce partage. Le premier texte décrivait déjà l’ajout d’états à l’historique; le second réunissait ajout et remplacement et montrait explicitement la reconstruction de l’écran après un événement. Le texte vivant de WHATWG continue de décrire ces méthodes dans un modèle de navigation plus large. L’essentiel tient en une formule de coulisses : le navigateur se souvient de l’ordre des actes, la page doit savoir à quoi ressemblait chacun d’eux.

Pour le lecteur, la règle paraît presque enfantine : Retour doit me ramener là où j’étais. L’API History a donné aux pages dynamiques de quoi tenir cette promesse sans recharger un document à chaque changement. Quand le bouton trouvait la bonne entrée et que la page restait sur la mauvaise scène, le bouton était le seul de la troupe à connaître son texte.