# Déboguer un mauvais INP après le passage à l’Interactivity API

> INP à 480 millisecondes après la migration d'un thème vers l'Interactivity API. Symptôme, diagnostic dans DevTools, correctif côté directives, et ce qu'il faut vérifier avant la prochaine migration.

- Auteur : Clément Hadrot
- Publié le : 2025-05-06
- Mis à jour le : 2025-05-06
- Catégorie : Performance
- URL : https://wpmoderne.dev.wordpress-developpement.fr/performance/deboguer-mauvais-inp-interactivity-api/

## L’essentiel

- Un INP dégradé après migration ne vient presque jamais du framework lui-même
- Le profileur Performance de DevTools isole la tâche longue en quelques minutes
- Un correctif ciblé sur une directive a suffi à retrouver un bon score

« INP: 480 ms — poor » : c'est ce qu'affichait le rapport Core Web Vitals de la Search Console, deux semaines après qu'un thème WordPress a migré ses interactions JavaScript vers l'Interactivity API stabilisée dans WordPress 6.5. Avant la migration, l'INP de ce même gabarit de page tournait autour de 140 millisecondes, largement dans la zone verte. Le code semblait pourtant plus propre qu'avant, débarrassé de plusieurs scripts jQuery legacy.

## Symptôme

L'interaction concernée était un simple accordéon de FAQ, converti pour utiliser les directives `data-wp-on--click` et `data-wp-bind` de l'Interactivity API à la place d'un gestionnaire d'événements jQuery classique. Sur le terrain, les utilisateurs signalaient un délai perceptible entre le clic sur une question et l'ouverture de la réponse, en particulier sur mobile d'entrée de gamme.

Le champ Interaction to Next Paint remplace le FID comme Core Web Vital officiel depuis mars 2024, et mesure la latence entre une interaction (clic, frappe, appui tactile) et la prochaine peinture visuelle qui en résulte à l'écran. Un INP élevé signale presque toujours une tâche JavaScript longue exécutée en réponse à l'interaction, qui empêche le thread principal de peindre la mise à jour attendue.

> L'essentiel à retenir : Un INP dégradé après migration ne vient presque jamais du framework lui-même ; Le profileur Performance de DevTools isole la tâche longue en quelques minutes ; Un correctif ciblé sur une directive a suffi à retrouver un bon score

## Diagnostic dans DevTools

L'onglet Performance de Chrome DevTools, avec un enregistrement centré sur le clic sur une question de la FAQ, a rapidement montré une tâche longue de 420 ms attribuée au store de l'Interactivity API. En zoomant sur la pile d'appels, la fonction en cause n'était pas le cœur du framework lui-même, mais un callback personnalisé enregistré via `store()`, qui recalculait la hauteur de chaque panneau de l'accordéon à chaque clic, y compris ceux qui restaient fermés.

- Le rapport « Long tasks » de DevTools isole directement les tâches dépassant 50 ms, seuil au-delà duquel le thread principal devient bloquant pour l'interaction suivante.
- Le panneau « Bottom-Up » de l'enregistrement Performance permet de remonter jusqu'à la fonction précise responsable du temps passé, plutôt que de rester au niveau du framework.
- Le champ `web-vitals` côté JavaScript, avec l'attribution activée, confirme l'élément DOM concerné par l'interaction lente.

## Ce que le code faisait réellement

```
// Callback appelé à chaque clic sur une question, pour TOUS les panneaux
store( 'accordeonFaq', {
    actions: {
        toggle: () => {
            const contexte = getContext();
            contexte.ouvert = ! contexte.ouvert;
            // Recalcul de hauteur sur l'ensemble des panneaux, pas seulement celui cliqué
            document.querySelectorAll( '.faq-panneau' ).forEach( ( panneau ) => {
                panneau.style.maxHeight = panneau.scrollHeight + 'px';
            } );
        },
    },
} );
```

La boucle `querySelectorAll` recalculait la hauteur de tous les panneaux de la page à chaque clic, provoquant un reflow complet du DOM à chaque interaction, un schéma qui passait inaperçu avec quelques questions en local mais qui devenait coûteux sur une FAQ de trente entrées en production.

## Correctif côté Interactivity API

La correction a consisté à limiter le recalcul de hauteur au seul panneau concerné par le contexte de l'interaction, en s'appuyant sur `getElement()` pour cibler précisément l'élément déclencheur plutôt que de reparcourir tout le DOM :

```
store( 'accordeonFaq', {
    actions: {
        toggle: () => {
            const contexte = getContext();
            contexte.ouvert = ! contexte.ouvert;
            const element = getElement();
            const panneau = element.ref.closest( '.faq-item' ).querySelector( '.faq-panneau' );
            panneau.style.maxHeight = contexte.ouvert ? panneau.scrollHeight + 'px' : '0px';
        },
    },
} );
```

Ce changement a fait retomber le temps de la tâche à environ 30 ms, sous le seuil de blocage perceptible, et l'INP mesuré en conditions réelles est redescendu à 150 ms en une semaine de collecte.

## Prévention pour les prochaines migrations

> Une migration vers l'Interactivity API ne dégrade jamais l'INP par elle-même : elle rend simplement visibles des schémas de code qui étaient déjà coûteux, mais masqués par une exécution jQuery moins instrumentée.

Avant toute migration de ce type, nous vérifions désormais systématiquement que les actions enregistrées via `store()` ciblent l'élément précis de l'interaction plutôt que l'ensemble du document, et nous ajoutons un enregistrement Performance de référence sur les interactions les plus fréquentes du gabarit avant de considérer la migration terminée.

## En résumé

Le mauvais INP de ce site ne venait pas de l'Interactivity API, mais d'un callback qui recalculait plus de travail que nécessaire à chaque clic, un défaut qui existait probablement avant la migration sous une autre forme. Le profileur Performance de DevTools reste l'outil le plus direct pour remonter du symptôme (interaction lente) jusqu'à la ligne de code exacte responsable, sans supposer que le framework est en cause avant d'avoir vérifié.
