Une page éditoriale peut télécharger et exécuter une application entière pour ouvrir un accordéon, changer une image ou suivre un clic. Le contenu est déjà présent, mais le navigateur analyse des centaines de kilo-octets, reconstruit l’arbre et attache des écouteurs à des zones que la majorité des visiteurs n’utilisera jamais.
Le vrai enjeu consiste à traiter JavaScript comme une capacité allouée à une interaction précise. Pour décider quoi charger, différer ou supprimer, le document reste rendu en HTML ; chaque îlot reçoit un budget, un déclencheur, un état minimal et un repli. Une zone ne devient interactive que si sa valeur, sa fréquence et sa complexité justifient son coût sur les appareils réellement exposés.
Le risque le plus révélateur est un taux d’utilisation inférieur au taux d’hydratation : 100 % des visiteurs paient pour une fonction utilisée par 3 %. Un autre signal est le chevauchement des tâches longues lorsque plusieurs îlots démarrent ensemble après le chargement, recréant le monolithe sous plusieurs fichiers.
Un audit de SEO technique et performance web rapproche valeur produit, HTML initial, graphe JavaScript et RUM. Il aide à supprimer, différer ou isoler chaque interaction sans fragiliser le contenu indexable.
Séparer document et interaction
Rendre le sens avant le comportement
Le serveur produit titre, texte, liens, médias, canonical et données structurées. L’îlot reçoit seulement la zone dont l’état doit évoluer dans le navigateur. Cette frontière évite de réhydrater le même contenu pour le rendre identique.
Un comparateur, une recherche instantanée ou un panier justifient souvent une logique client. Un sommaire, une navigation et une fiche de lecture fonctionnent d’abord avec HTML et CSS, puis s’enrichissent si nécessaire.
Refuser l’uniformité technique
Toutes les pages ne partagent pas la même densité interactive. Imposer un runtime commun à une publication et à un configurateur fait payer la complexité maximale au parcours le plus simple.
Contre-intuitivement, conserver quelques comportements natifs peut améliorer cohérence, accessibilité et maintenance davantage qu’un système d’îlots exhaustif. L’objectif est moins de JavaScript utile, pas davantage de frontières.
Inventorier les interactions réelles
Observer les parcours, pas le code
L’inventaire part des clics, saisies, expansions, changements de variante et soumissions. Il indique fréquence, moment, valeur et appareil. Une fonction présente dans le composant mais jamais utilisée ne mérite pas un budget automatique.
Les événements sont agrégés sans données personnelles. Ils distinguent visibilité de l’îlot et utilisation : un taux faible peut venir d’une fonction inutile ou simplement d’une zone rarement atteinte.
Repérer les interactions dépendantes
Une sélection de variante peut mettre à jour prix, image, stock et URL. La découper artificiellement en quatre îlots crée messages, états dupliqués et courses. Une frontière cohésive est préférable.
À l’inverse, le chat, la vidéo et les recommandations n’ont aucune raison de partager le runtime du formulaire principal. Leur cycle de vie et leur consentement restent indépendants.
Noter la valeur de chaque îlot
Croiser valeur, fréquence et urgence
La grille mesure contribution au parcours, proportion d’utilisateurs, nécessité avant interaction, complexité du repli et coût CPU. Une fonction rare mais critique peut charger à l’intention ; une fonction fréquente et légère peut démarrer tôt.
La note produit une décision : HTML natif, interaction légère, îlot différé, îlot immédiat ou suppression. Elle ne sert pas à justifier après coup tous les composants existants.
Inclure le coût de maintenance
Chaque îlot ajoute build, données, erreurs, observation et tests. Dix petits bundles peuvent multiplier les versions et dépendances même si leur poids total paraît réduit.
Le coût caché inclut l’orchestration : priorité, préchargement, état partagé et mises à jour. Une frontière qui nécessite une infrastructure disproportionnée revient au tableau pour être simplifiée.
Dessiner des frontières stables
Conserver une responsabilité complète
Un îlot possède une action compréhensible, son état et ses erreurs. Il ne dépend pas d’un contexte global immense pour afficher un bouton. Les données partagées sont limitées à un contrat explicite.
Le DOM serveur fournit une racine stable et des attributs versionnés. L’îlot n’efface pas ses voisins et ne déplace pas le contenu essentiel lors de son démarrage.
Éviter les arbres imbriqués concurrents
Deux runtimes ne doivent pas contrôler les mêmes nœuds. Les îlots imbriqués ont une propriété claire ou communiquent par événement documenté, sans réhydrater deux fois le sous-arbre.
Les styles critiques existent avant activation. La prise de contrôle ne provoque ni CLS ni flash de contenu remplacé. Les dimensions et états fermés sont réservés dans le HTML.
Choisir le bon déclencheur
Charger à la nécessité
Un contrôle visible et immédiatement probable peut charger tôt. Une zone sous la ligne de flottaison attend sa proximité. Une fonction ouverte par clic peut précharger à l’intention, puis s’activer à l’action.
Le déclencheur tient compte de la connexion, du CPU et du consentement. Une temporisation arbitraire après chargement empile souvent les tâches longues au moment où l’utilisateur commence à agir.
Protéger la première interaction
Si le code n’est pas prêt au clic, le contrôle conserve un comportement natif ou indique un état bref sans perdre l’action. La première saisie ne doit jamais disparaître pendant le chargement.
Le préchargement s’annule lorsque l’îlot quitte le viewport ou que la navigation change. Télécharger après abandon gaspille données et concurrence réseau.
Limiter données et dépendances
Sérialiser un état minimal
L’îlot reçoit identifiant public, version, locale et données nécessaires à son premier rendu. Il ne transporte ni session complète ni catalogue entier. Les valeurs sensibles restent côté serveur.
La sérialisation est échappée et compatible entre versions. Un déploiement progressif maintient la lecture de l’ancien contrat pendant la durée maximale du cache HTML.
Éviter les requêtes dupliquées
Plusieurs îlots qui lisent la même donnée utilisent une couche bornée ou une réponse partagée, sans créer un gestionnaire global pour tout le site. Les clés et durées restent explicites.
Une donnée déjà présente dans le HTML n’est pas immédiatement rechargée. Sa politique de fraîcheur décide quand une requête apporte réellement une information nouvelle.
Fixer un budget par composant
Mesurer transfert, analyse et exécution
Le budget inclut JavaScript compressé, dépendances partagées, temps de compilation et tâches déclenchées. Un bundle léger peut rester cher s’il construit un grand état ou parcourt tout le DOM.
Les mesures utilisent appareils modestes et percentiles terrain. Le laboratoire valide le mécanisme ; le RUM montre le coût sur les cohortes réellement exposées.
Empêcher la dette cumulative
La CI compare le budget de chaque îlot et le total d’une page. Ajouter 8 Ko à cinq composants est une hausse de 40 Ko, même si aucun seuil individuel n’est franchi.
Une exception nomme propriétaire, valeur, date et plan de retrait. Sans preuve d’utilisation, le prochain arbitrage commence par supprimer plutôt que relever le plafond.
Préserver le repli natif
Utiliser les primitives du navigateur
Les liens possèdent une destination, les formulaires une action, les détails un état natif et les boutons une fonction claire. JavaScript améliore validation, retour ou transition sans supprimer le chemin de base.
Le clavier, le focus, les lecteurs d’écran et le retour navigateur sont testés avant et après activation. Une fonction plus dynamique mais moins utilisable ne justifie pas son îlot.
Gérer l’échec localement
Une ressource absente laisse le HTML visible. Une requête en erreur conserve l’ancienne information si elle reste sûre ou affiche un message dans la zone. Le reste du document ne remonte pas.
L’utilisateur peut réessayer sans créer une boucle. Les actions transactionnelles conservent idempotence et preuve ; une animation facultative disparaît simplement.
Mesurer utilisation et coût terrain
Associer activation et valeur
Le tableau montre visibilité, chargement, activation, première interaction, réussite et abandon par îlot. Il rapproche ces volumes du transfert, du temps CPU et des tâches longues.
Un îlot chargé dans 100 % des sessions mais utilisé dans 2 % devient candidat à l’intention. Un îlot souvent utilisé mais lent demande simplification ou préchargement ciblé.
Segmenter sans exploser la cardinalité
Les métriques retiennent gabarit, version, appareil et type de connexion, jamais un identifiant individuel. Les erreurs sont regroupées par signature.
L’INP et les tâches longues sont attribués à l’activation ou à l’interaction correspondante. Une valeur page globale ne permet pas de choisir quel composant corriger.
Arbitrer un cas entièrement simulé
Quantifier un catalogue fictif
Par exemple, imaginons une fiche entièrement simulée chargeant 310 Ko de JavaScript pour galerie, avis, recommandation et disponibilité. Seuls 18 % des visiteurs ouvrent la galerie et 4 % les avis, tandis que l’INP p75 mobile atteint fictivement 360 ms. Ces nombres ne viennent d’aucun client ni de Dawap.
La variante et l’ajout panier restent immédiats dans un îlot de 48 Ko. La galerie charge à l’intention, les avis au viewport et la recommandation après disponibilité CPU. Le transfert médian fictif tombe à 92 Ko et l’INP p75 à 190 ms.
Décider avec des seuils explicites
Le canari bloque si une action native échoue, si un îlot ajoute plus de 50 ms de tâche longue p75 ou si le total initial dépasse 100 Ko. Une baisse d’utilisation inattendue déclenche une vérification fonctionnelle.
Les seuils illustrent une méthode et doivent être calibrés sur les appareils, la valeur et les bundles réels. Le gain n’est accepté que si le parcours reste complet.
Recetter îlots et orchestration
Tester chaque îlot isolément
La matrice couvre HTML seul, bundle absent, données lentes, erreur, activation répétée et navigation avant chargement. Elle vérifie état, focus, repli et absence de duplication d’écouteurs.
Le composant est aussi testé sur CPU ralenti et connexion limitée. Une interaction immédiate sur poste puissant peut perdre le premier clic sur un mobile courant.
Tester la page complète
Les îlots démarrent ensemble selon les déclencheurs réels. La recette mesure concurrence réseau, tâches longues cumulées, CLS et ordre de focus. Elle provoque plusieurs interactions rapprochées.
Un budget total complète les seuils individuels. La page doit rester stable même si un îlot tiers ou secondaire ne charge jamais.
Gouverner les nouvelles interactions
Exiger un dossier de valeur
Toute nouvelle interaction précise utilisateur, fréquence attendue, comportement natif, poids, dépendances et mesure de réussite. Le design et le produit valident la valeur avant le choix du framework.
Une expérience possède une date d’arrêt. Son îlot, ses événements et ses dépendances sont retirés lorsque la décision est prise, sans conserver un bundle inactif.
Attribuer la propriété du budget
Chaque composant a un responsable technique et produit. Les alertes de taille, erreurs et utilisation arrivent aux mêmes propriétaires. Une bibliothèque partagée possède sa propre gouvernance.
Les exceptions expirent. Le comité ne discute pas de chaque octet, mais refuse les hausses sans valeur mesurable ni plan de repli.
Éviter les îlots décoratifs
Découper sans réduire le runtime
Créer dix points d’entrée qui embarquent tous le même framework ne réduit ni analyse ni mémoire. Le graphe réel doit confirmer quels modules sont mutualisés, dupliqués ou évités.
Autre erreur : hydrater au viewport tous les blocs d’une longue page. Un défilement rapide déclenche alors plusieurs téléchargements simultanés sans intention d’usage.
Mesurer seulement le poids
Le transfert compressé ignore analyse, exécution, données et fréquence. Les budgets incluent CPU et valeur. Une librairie compacte peut encore monopoliser le thread principal.
Enfin, oublier le retrait transforme chaque expérience en dette permanente. La gouvernance doit savoir supprimer un îlot aussi facilement qu’elle sait l’ajouter.
Plan d’action : migrer en trois semaines
Semaine 1 : inventorier et classer
L’équipe mesure interactions, visibilité, bundles, CPU et dépendances sur quelques gabarits. Elle documente le comportement HTML et choisit suppression, natif, différé ou immédiat.
Le livrable nomme frontières, déclencheurs, budgets et responsables. Les actions sans repli ou données trop larges restent hors migration.
Semaines 2 et 3 : isoler puis ouvrir
La deuxième semaine extrait un îlot à forte valeur et plusieurs composants supprimables. La troisième exécute tests isolés, page complète, RUM canari et rollback.
L’extension exige un HTML complet, un budget total respecté et une utilisation au moins conforme au témoin. Un composant qui ne crée aucun gain reste natif ou disparaît.
La mise en œuvre attribue responsabilités, dépendances, seuils CPU, instrumentation, journalisation et repli à chaque îlot. Le monitoring relie logs, JavaScript, hydratation, HTML, routes et TTFB. La CI puis la QA vérifient canonical, indexation, crawl Googlebot et comportement natif avant d’autoriser un déclencheur plus précoce.
Cas concret : si un îlot ajoute plus de 50 ms de tâche longue p75 ou si sa réussite baisse de 1 %, alors l’équipe revient d’abord au repli HTML. Elle compare bundle, données et interaction, puis ne réactive qu’après deux canaris où l’usage progresse sans dégrader l’INP ni dupliquer les requêtes de rendu.
- D’abord, nommer usage, visibilité et coût par interaction.
- Ensuite, tester le choix natif, différé, immédiat ou supprimé.
- Puis, décider depuis données, runtime et tâches longues.
- Enfin, ouvrir après un canari utile et réversible.
Pour qui l’hydratation partielle vaut son coût
Comparer les composants dans un même budget
Les équipes classent les îlots selon valeur observée, sessions exposées, coût CPU, taille marginale et risque fonctionnel. Un configurateur fortement utilisé peut consommer davantage qu’une animation, mais il doit alors évincer des fonctions moins utiles plutôt que relever automatiquement le budget total de la page.
La revue examine également les dépendances partagées. Deux composants modestes qui imposent deux runtimes différents peuvent coûter davantage qu’un îlot cohésif. À l’inverse, une bibliothèque commune ne doit pas devenir obligatoire pour une route qui n’utilise qu’un comportement natif. Le graphe réel tranche ces cas.
Chaque frontière précise ses entrées, ses sorties, son propriétaire et son repli. Une galerie peut recevoir seulement les URL et descriptions nécessaires, puis émettre un changement d’image sans connaître le panier. Cette autonomie borne les dépendances et rend le composant testable hors page. Si l’îlot exige l’état complet du produit, du consentement et de la navigation, la frontière est probablement dessinée trop large.
Le budget est aussi collectif : le gain d’un îlot ne justifie pas une régression globale. La revue additionne transfert, compilation, exécution et chevauchement des tâches, puis compare le p75 sur appareils modestes. Un composant respecte sa limite individuelle mais reste refusé s’il déclenche avec deux voisins une longue tâche qui détériore l’interaction principale.
Organiser la suppression comme une livraison
Retirer un îlot demande de supprimer son point d’entrée, ses données, ses événements, ses styles et ses règles de consentement. Le canari compare alors parcours, conversion et support à la cohorte témoin. Une absence d’effet confirme que le code n’apportait plus la valeur qui justifiait son entretien.
Le produit conserve la date, la preuve et la décision. Si une fonction doit revenir, elle repasse par la grille au lieu de réactiver un ancien bundle devenu incompatible. Cette discipline transforme le budget JavaScript en portefeuille vivant, avec entrées, arbitrages et sorties explicites.
La suppression possède son propre rollback, mais il ne consiste pas à conserver indéfiniment deux chemins actifs. L’équipe fixe un seuil d’abandon, observe le monitoring pendant une cohorte représentative et ferme la dépendance dès validation. La journalisation relie version, événement et résultat métier ; elle distingue ainsi une interaction réellement perdue d’un suivi analytique devenu obsolète.
Enfin, le retrait doit améliorer le contrat, pas seulement le poids du bundle. Les tests vérifient le lien natif, le focus, l’historique, la canonical et le HTML sans JavaScript. Le support connaît le changement visible, la QA rejoue les appareils les plus contraints et le produit confirme que la fonction supprimée n’était plus un passage obligé.
Consulter les sources et prolongements
Comparer les architectures
La documentation web.dev sur le rendu sur le Web présente les compromis de rendu. La documentation officielle d’Astro sur l’architecture en îlots décrit la séparation entre HTML statique et zones interactives.
Ces références cadrent l’architecture ; la valeur et le budget doivent provenir des parcours du site.
Prolonger la mesure
L’analyse de l’échec d’hydratation approfondit le repli. L’étude de la personnalisation tardive et du CLS aide à borner les zones qui évoluent après le rendu.
La première ressource protège le contenu lorsque la reprise échoue ; la seconde cadre les changements visuels provoqués après le document initial. Ensemble, elles évitent d’attribuer au découpage un gain qui vient seulement d’une mesure incomplète.
Conclusion : charger ce qui agit
L’hydratation partielle n’est pas un concours de découpage. Elle alloue du JavaScript aux interactions dont la valeur dépasse le coût réel.
Le document garde son sens, ses liens et ses replis. Les îlots possèdent des frontières cohésives, des données minimales et un déclencheur lié à l’intention.
La preuve associe utilisation, transfert, CPU, INP et réussite fonctionnelle. Un budget par composant et par page empêche le monolithe de se reformer.
Pour cartographier vos interactions, réduire le runtime et protéger les parcours, notre accompagnement en SEO technique transforme chaque îlot en décision produit mesurable.