Accueil / Articles / Des réponses aux entretiens sur React et JavaScript qui démontrent une véritable profondeur.

Des réponses aux entretiens sur React et JavaScript qui démontrent une véritable profondeur.

Découvrez des réponses plus solides et plus nuancées aux questions fréquentes lors d’entretiens sur React et JavaScript, allant du Virtual DOM à la conception de systèmes, qui illustrent un jugement technique plus approfondi.

3825 mots

Introduction : Pourquoi la plupart des candidats ont tous le même ton

Si vous assistez à suffisamment d’entretiens sur React, vous remarquerez un schéma récurrent : les mêmes phrases toutes faites reviennent sans cesse. « Le Virtual DOM est plus rapide. » « useEffect sert aux effets secondaires. » « JavaScript s’exécute sur un seul thread. » Aucune de ces affirmations n’est fausse, mais ce sont des choses que n’importe qui pourrait réciter après avoir lu quelques articles de blog, et elles ne donnent aucune idée à l’interlocuteur sur la façon dont vous réfléchissez vraiment.

Ce qui distingue un candidat solide de celui qui se voit envoyer un e-mail de refus poli, ce n’est pas s’il connaît la définition théorique — c’est s’il peut aller plus en profondeur. Pouvez-vous relier un concept aux compromis qui le sous-tendent ? Pouvez-vous expliquer pourquoi une décision de conception a été prise, et non seulement ce qu’elle fait ? C’est le type de jugement que les interviewers cherchent réellement à évaluer.

Ce guide aborde les questions qui se posent réellement lors des entretiens pour des postes de niveau intermédiaire et avancé en développement frontend, accompagnées de réponses suffisamment détaillées pour inciter l’entreteneur à cesser de parcourir ses notes et à écouter vraiment.

Section 1 : Concepts fondamentaux de React

Question 1 : « Expliquez le Virtual DOM. Comment fonctionne-t-il ? »

La réponse banale : « Le Virtual DOM est une copie légère du vrai DOM. React compare les deux et ne met à jour que ce qui a changé, ce qui le rend plus rapide. »

La réponse plus approfondie : le Virtual DOM est une abstraction, mais le décrire uniquement comme « plus rapide » manque l’essentiel. L’avantage réel en termes de performance ne provient pas du Virtual DOM lui-même, mais de la logique de regroupement des mises à jour et de conciliation qui lui est associée.

React gère en interne deux arbres : celui qui est actuellement affiché à l’écran, et un arbre en cours de création représentant ce qui va être rendu. Lorsque l’état change, React ne se précipite pas pour modifier directement le DOM réel. Au lieu de cela, il construit le nouvel arbre Virtual DOM, effectue une comparaison pour déterminer l’ensemble minimal de modifications nécessaires, puis applique toutes ces modifications au DOM réel en une seule opération groupée. C’est précisément cette étape de regroupement qui évite des recalculs répétés du layout, souvent appelés problèmes de performance liés au layout.

Il y a aussi une nuance à mentionner : le Virtual DOM n’est pas gratuit. Son algorithme de comparaison est délibérément maintenu à une complexité O(n) en s’appuyant sur des heuristiques — par exemple, en supposant que des éléments de types différents produiront des sous-arbres entièrement distincts — plutôt qu’en effectuant une comparaison d’arbres complètement générale de complexité O(n³). Ce compromis permet de conserver des performances rapides dans les cas courants, mais cela signifie que certains scénarios, comme une liste très longue où un seul élément change, peuvent encore être coûteux en ressources. C’est précisément pour cette raison qu’il existe des outils tels que React.memo, useMemo et des bibliothèques de virtualisation de listes.

Il convient également de reconnaître que le Virtual DOM perd progressivement de son attrait en tant que point fort unique. Des compilateurs comme celui de Svelte évitent complètement l’étape du Virtual DOM, et React lui-même se dirige vers des fonctionnalités de rendu concurrentiel qui modifient le fonctionnement réel du processus de conciliation. Le Virtual DOM a résolu un problème spécifique vers 2013 ; comprendre pourquoi il a été introduit est plus important que de pouvoir réciter ses mécanismes.

Répondre de cette manière montre une conscience historique, une reconnaissance honnête des compromis à faire, ainsi qu’une connaissance de l’évolution du paysage frontend en général — vous ne répondez pas seulement à la question littérale, mais vous démontrez également que vous comprenez où cette idée s’inscrit dans le tableau global.

Question 2 : « Quelle est la différence entre useEffect, useLayoutEffect, et dans quels cas les utiliser ? »

La réponse oubliable : « useEffect s’exécute après le rendu. useLayoutEffect s’exécute avant que le navigateur ne dessine l’écran. Utilisez useLayoutEffect lorsque vous devez mesurer le DOM. »

La réponse plus solide : la distinction liée au moment d’exécution est de notoriété publique, mais c’est l’explication du pourquoi de cette différence qui distingue une réponse pertinente. useEffect s’exécute de manière asynchrone, après que le navigateur a déjà dessiné l’écran. useLayoutEffect, en revanche, s’exécute de manière synchrone, juste après que React a terminé le calcul des modifications du DOM, mais avant que le navigateur n’ait eu le temps de dessiner.

Cette différence signifie que useLayoutEffect bloque en réalité la mise à jour visuelle. Si vous y placez des calculs coûteux, l’utilisateur percevra un écran figé. C’est précisément pour cette raison que la documentation React recommande d’utiliser par défaut useEffect — bloquer inutilement le dessin est un piège de performance courant.

Néanmoins, il existe des raisons légitimes d’utiliser useLayoutEffect au-delà de la simple « mesure du DOM ». Un bon cas d’usage est d’éviter des clignotements visibles. Imaginez qu’il s’agisse de rendre une boîte à outils dont la position dépend des dimensions d’un élément cible : effectuer ce calcul de positionnement à l’intérieur de useEffect provoque un éclairage visible, où la boîte à outils apparaît brièvement au mauvais endroit avant de se placer correctement. Effectuer ce même calcul à l’intérieur de useLayoutEffect évite complètement cet éclairage, car il a lieu avant que le navigateur ne dessine quoi que ce soit.

Il existe un troisième hook dans cette famille que de nombreux développeurs négligent : useInsertionEffect. Son but est de permettre aux outils CSS-in-JS d’insérer des règles de style dans le document avant que les effets de mise en page ne lisent par erreur des informations de style obsolètes depuis le DOM. La plupart des développeurs n’auront jamais besoin de l’utiliser directement, mais le simple fait de savoir qu’il fait partie du cycle de vie des effets de React indique une meilleure compréhension de la manière dont React 18 gère globalement les effets.

Un intervieweur pourrait insister et demander ce qui se passe si l’on utilise useLayoutEffect lors du rendu côté serveur. La réponse est que React vous avertira, car il n’y a pas de DOM disponible pour effectuer des mesures sur le serveur. Ce hook ne s’exécute tout simplement pas pendant le SSR, donc toute logique dépendante du DOM doit soit être protégée par une condition réservée au client, soit être déplacée dans useEffect.

Question 3 : « Expliquez le comportement de rendu de React. Quand un composant est-il rérendu ? »

La réponse banale : « Un composant est rérendu chaque fois que son état ou ses props changent. »

La réponse plus précise : ce n’est que la surface des choses. La question intéressante est de savoir ce qui compte réellement comme un « changement » et ce que fait React une fois qu’il en détecte un.

Un composant est rérendu dans trois conditions :

  1. Son état local change, généralement via un setteur d’état
  2. Son composant parent est rérendu, que les props transmis aient effectivement changé ou non
  3. Une valeur de contexte qu’il consomme change

La réflexion clé concerne le deuxième point : React ne compare pas les props avant de décider s’il faut rérender un composant enfant. Par conception, si un parent est rendu, ses enfants le sont également. Comparer les props n’est pas sans coût en termes de calcul, et dans la plupart des cas réels, le composant enfant doit de toute façon être mis à jour ; donc omettre cette comparaison par défaut constitue un compromis raisonnable.

C’est précisément là que les développeurs recourent à React.memo, souvent de manière erronée. La mémorisation a elle-même un coût — React doit toujours effectuer une comparaison des props lors de chaque rendu. Si ces props sont des objets complexes, ou si le composant concerné est déjà peu gourmand en ressources lors de son rendu, l’envelopper dans React.memo peut en fait nuire aux performances plutôt que de les améliorer.

La véritable compétence réside dans la capacité à savoir quand l’optimisation est vraiment justifiée. Une règle pratique consiste à éviter de mettre en mémoire les résultats avant d’avoir mesuré un problème concret. Utilisez le Profilleur des outils de développement React pour identifier d’abord les véritables goulots d’étranglement, puis appliquez React.memo, useMemo ou useCallback de manière ciblée. Optimiser prématurément dans React signifie généralement travailler à l’encontre de la conception du framework plutôt qu’avec elle.

Le rendu concurrentiel introduit par React 18 ajoute une couche supplémentaire à ce processus. Les rendus peuvent désormais être interrompus, priorisés ou même annulés en cours d’exécution. Comprendre qu’un rendu ne se traduit pas toujours directement par une mise à jour synchrone du DOM est essentiel pour écrire du code qui fonctionne correctement dans un environnement de rendu concurrentiel.

Question 4 : Comment gérer la gestion de l’état dans une grande application React ?

useState pour tout ce qui est local.

  • État UI local : valeurs de formulaire, interrupteurs, état d’ouverture d’un modal. useState suffit dans ce cas.
  • État serveur : données récupérées depuis un backend. React Query ou SWR sont conçus pour cela, car ils gèrent déjà le cache, la déduplication, la récupération en arrière-plan et les mises à jour optimistes — des fonctionnalités pour lesquelles Redux n’a jamais été conçu.
  • État client partagé : des éléments tels que les préférences de l’utilisateur, le statut d’authentification ou des indicateurs fonctionnels. Le contexte est suffisant lorsque les mises à jour sont rares ; Zustand ou Jotai conviennent mieux lorsque l’état change fréquemment ou comporte de nombreuses composantes dynamiques.
  • État URL : filtres, pagination et paramètres de recherche. Cet élément doit figurer dans l’URL plutôt que dans un stockage d’état, car il permet des liens partageables et une navigation correcte via le bouton Retour sans aucun code supplémentaire.
  • Section 2 : Approfondissements sur JavaScript

    Question 5 : Expliquez les closures en JavaScript. Donnez un exemple concret.

    Une réponse de surface décrit une fermeture comme étant simplement une fonction qui conserve les variables de son scope d’encadrement.

    Une réponse plus approfondie relie cela au scope lexical : lorsqu’une fonction est créée, elle capture des références aux variables qui l’entourent à ce moment-là, et elle conserve un accès à celles-ci même après que l’exécution soit passée en dehors de ce scope initial.

    Ce qui distingue un bon candidat, c’est sa capacité à expliquer pourquoi ce comportement est important spécifiquement dans React. Prenons un schéma qui provoque fréquemment des erreurs :

    function Counter() {
      const [count, setCount] = useState(0);
    useEffect(() => {
        const timer = setInterval(() => {
          console.log(count); // Always logs 0
          setCount(count + 1); // Resets to 1 every time
        }, 1000);
      }, []); // Empty deps = closure over initial count
    }
    

    La variable count référencée à l’intérieur de setInterval reste bloquée sur la valeur qu’elle avait lors du rendu initial. Comme l’effet s’exécute une seule fois, grâce au tableau de dépendances vide, cette clôture n’est jamais mise à jour avec de nouvelles valeurs. Ajouter simplement count à la liste des dépendances n’est pas non plus la solution adéquate, car cela entraînerait la destruction et la reconstruction de l’intervalle à chaque mise à jour. La solution appropriée consiste à utiliser la forme d’actualisation fonctionnelle, setCount(c => c + 1), qui évite complètement de dépendre de cette clôture obsolète.

    Les clôtures provoquent également des conflits avec les écouteurs d’événements à l’intérieur des hooks personnalisés. Chaque fois qu’un écouteur est attaché à l’intérieur de useEffect et qu’il lit des données d’état, une clôture est impliquée. Une technique courante pour un hook de type useEventListener consiste à conserver la fonction de traitement dans un ref, afin que l’écouteur puisse toujours accéder à la version la plus récente sans avoir besoin d’être réattaché.

    Rien de tout cela ne fait des clôtures quelque chose à éviter — ce sont un mécanisme fondamental qu’il convient de maîtriser. Les modèles de modules, les variables privées, les fonctions de fabrication et le currying dépendent tous d’elles. La compétence essentielle consiste à reconnaître précisément quand une clôture est créée et à s’assurer qu’elle capture bien la valeur prévue.

    Question 6 : Qu’est-ce que le cycle d’événements ? Expliquez les microtâches et les macrotâches.

    Une réponse sommaire indique que le cycle d’événements gère les tâches asynchrones et que les microtâches s’exécutent avant les macrotâches.

    Une réponse plus détaillée explique que JavaScript s’exécute sur un seul thread, et que le navigateur simule la concurrence grâce au cycle d’événements. Le code synchrone s’exécute sur la pile d’appels ; lorsqu’une opération asynchrone est rencontrée, elle est transmise à une API Web — setTimeout, fetch, événements DOM — et une fois ce travail terminé, sa fonction de rappel est placée dans une file d’attente.

    La subtilité à souligner est qu’il n’y a pas une seule file d’attente. Les macro-tâches — setTimeout, setInterval, les opérations I/O — sont placées dans une file, tandis que les micro-tâches — Promise.then, queueMicrotask, MutationObserver — le sont dans une autre. Une fois la pile d’appels vide, le cycle d’événements vide toute la file des micro-tâches avant même de traiter une seule macro-tâche.

    Cela crée un risque réel : les micro-tâches peuvent priver le reste du programme de ressources. Si de nouvelles micro-tâches continuent d’être enregistrées de manière récursive, les callbacks de setTimeout en attente n’auront jamais leur tour. Ce type de situation peut paralyser l’interface utilisateur lorsque des Promises sont enchaînées en boucle sans jamais restituer le contrôle au navigateur.

    Cela est directement lié à la manière dont React regroupe les mises à jour d’état. Dans React 18, les mises à jour d’état sont regroupées automatiquement, quel que soit leur point de départ : à l’intérieur de setTimeout, dans une Promise ou dans un gestionnaire d’événement natif. Ce n’était pas le cas avant React 18, où les mises à jour déclenchées à l’intérieur de setTimeout étaient appliquées une par une au lieu d’être regroupées. Comprendre le cycle d’événements permet de voir pourquoi le regroupement automatique de React 18 est important : il s’articule avec la file d’attente des microtâches afin que toutes les mises à jour en attente soient exécutées ensemble avant le prochain rendu.

    On vous demandera peut-être également de prédire la sortie d’un court extrait comme celui-ci :

    console.log('1');
    setTimeout(() => console.log('2'), 0);
    Promise.resolve().then(() => console.log('3'));
    console.log('4');
    

    La réponse attendue est : 1, 4, 3, 2 — les instructions synchrones s’exécutent en premier, suivies des microtâches telles que la fonction de rappel de Promise, et ce n’est qu’ensuite que s’exécute la macrotâche enregistrée par setTimeout.

    Question 7 : « Expliquez this en JavaScript. En quoi diffère-t-il des autres langages ? »

    La réponse sommaire : « this fait référence à l’objet qui a appelé la fonction. »

    La réponse approfondie : « En JavaScript, this suit un encadrement dynamique plutôt qu’un encadrement lexical. La plupart des langages définissent self ou this au moment où la fonction est définie. JavaScript, quant à lui, le résout au moment de l’appel, en fonction de la manière dont la fonction est invoquée et non de son emplacement dans le code source. »

    « Il existe un ordre de priorité pour quatre règles de liaison :

    1. Liaison par création : new Foo() définit this sur l’instance nouvellement créée
    2. Liaison explicite : foo.call(obj), foo.apply(obj) ou foo.bind(obj) forcent this à être l’objet que vous passez en paramètre
  • Lien implicite : l’appel de obj.foo() fait en sorte que this soit égal à obj
  • Lien par défaut : un appel simple de foo() laisse this égal à undefined en mode strict, ou recourt à globalThis dans le cas contraire"
  • ">Les fonctions flèche brisent délibérément ce schéma — elles héritent this de manière lexique du contexte qui les entoure. C’est précisément pour cette raison que les développeurs utilisaient des fonctions flèche à l’intérieur des composants React basés sur des classes avant l’apparition des hooks : cela leur permettait d’éviter de devoir appeler .bind(this) à l’intérieur du constructeur."

    « Le code React basé sur les hooks ne touche que rarement directement à this, puisque les composants ne sont plus des classes. Néanmoins, ce concept réapparaît lorsque l’on maintient des composants de classe anciens, qu’on intègre des bibliothèques tierces ou face à un intervieweur qui souhaite vérifier sa maîtrise des fondamentaux de JavaScript. Un piège courant dans la pratique est de passer une méthode d’objet en tant que callback — par exemple, de transmettre obj.handleClick à un écouteur d’événement — ce qui supprime son liaison implicite et fait en sorte que this pointe vers une destination inattendue. »

    Question 8 : « Qu’est-ce que les Promises en JavaScript ? Expliquez async/await. »

    La réponse sommaire : « Les Promises gèrent le travail asynchrone, et async/await n’est rien d’autre qu’un sucre syntaxique ajouté par-dessus elles. »

    La réponse clé : « Une Promise représente une valeur qui n’existe pas encore mais qui sera finalement déterminée. Elle remplace les chaînes complexes de callbacks par une interface chainable et un moyen cohérent d’indiquer le succès ou l’échec. »

    « Ce qui rend les Promises véritablement utiles, ce n’est pas leur syntaxe mais les garanties qu’elles offrent. Une fois qu’une Promise est résolue – que ce soit en état satisfait ou rejeté – ce résultat est fixé et ne peut jamais changer. C’est cette immuabilité qui les rend composables et faciles à comprendre. »

    « Dire que async/await n’est « qu’un sucre ajouté » en sous-estime son importance : il redéfinit fondamentalement la manière d’écrire de la logique asynchrone, lui permettant de ressembler à du code synchrone et facilitant grandement sa lecture. Cela dit, il introduit quelques pièges auxquels il convient de faire attention : »

    // This runs sequentially - 6 seconds total
    async function sequential() {
      const a = await fetch('/a'); // 3s
      const b = await fetch('/b'); // 3s
    }
    // This runs in parallel - 3 seconds total
    async function parallel() {
      const [a, b] = await Promise.all([fetch('/a'), fetch('/b')]);
    }
    

    « Une erreur fréquente chez les développeurs moins expérimentés consiste à placer await à l’intérieur d’une boucle, ce qui force involontairement les opérations à s’exécuter une après l’autre plutôt que en parallèle. La solution consiste à utiliser Promise.all chaque fois que les opérations ne dépendent pas les unes des autres, et à réserver une boucle for...of avec await aux cas où une séquence stricte est effectivement requise. »

    « La gestion des erreurs est un autre domaine où des problèmes surviennent. En enveloppant une appel à await dans try/catch, on peut capturer son échec, mais omettre cet enveloppement peut entraîner l’effondrement d’un processus Node.js en cas d’échec non géré. Au frontend, en enveloppant les appels asynchrones dans des bornes d’erreur ou en utilisant une bibliothèque comme React Query qui gère les états d’erreur de manière déclarative, on évite ce mode de défaillance. »

    Section 3 : Conception du système et architecture

    Question 9 : « Concevez un éditeur de documents collaboratif en temps réel comme Google Docs. »

    Cette question change complètement l’orientation de l’interview. Le recruteur ne cherche plus à évaluer vos connaissances basiques sur React — il veut voir comment vous raisonnez en matière d’architecture de système.

    Une approche solide serait la suivante :

    « Avant d’écrire ne serait-ce qu’une ligne de code, je définirais clairement les exigences :

    • Combien de personnes vont éditer en même temps ? La conception pour 10 utilisateurs simultanés est très différente de celle prévue pour 10 000.
    • Quelle latence est acceptable — un temps réel absolu, ou plutôt quelque chose de proche du quasi-temps réel ?
    • L’application doit-elle fonctionner hors ligne ?
    • Quelle stratégie de résolution des conflits allons-nous adopter ? »

    « Du côté frontend : »

    • Gestion de l’état : chaque client conserve sa propre copie locale du document. Les modifications sont d’abord appliquées de manière optimiste sur le client, puis envoyées au serveur, qui les transmet à tous les autres clients connectés.
    • Transformation opérationnelle ou CRDT : c’est le mécanisme permettant de résoudre les modifications conflictuelles. La transformation opérationnelle était la technique originale de Google, mais elle dépend d’un serveur central pour arbitrer l’ordre des modifications. Les CRDT (Conflict-free Replicated Data Types) peuvent fonctionner en pair-à-pair, et des outils tels que Yjs en ont accru l’utilisation.
  • Intégration React : le composant éditeur s’affiche à partir de l’état du document partagé. Les opérations distantes arrivent via une connexion WebSocket et passent par une étape de transformation avant d’actualiser l’état local. En conservant l’instance de l’éditeur dans un ref plutôt que dans l’état React, on évite de déclencher un re-render à chaque frappe — l’état React est réservé uniquement aux éléments visuels tels que la position du curseur, les avatars des collaborateurs et les indicateurs de présence.
  • Prestations : virtualisation de l’affichage pour les documents volumineux, regroupement des mises à jour UI avec requestAnimationFrame, et débouncing des synchronisations réseau afin de ne pas envoyer de requête à chaque frappe.
  • "Au niveau de la synchronisation :

    • WebSocket gère le transport en temps réel
    • Server-Sent Events ou long-polling servent de solution de secours si la connexion WebSocket ne peut pas être établie
    • Les données de présence — qui est en ligne et où se trouve son curseur — sont transmises via un canal léger distinct du contenu du document"

    "La partie véritablement difficile de ce problème n’a rien à voir avec le rendu React — c’est le modèle de cohérence qui se trouve en dessous. Lorsque deux personnes tapent à exactement la même position du curseur au même instant, que se passe-t-il ? La réponse dépend entièrement du choix entre OT et CRDTs, et cette seule décision influence presque toutes les autres choix architecturaux qui suivent."

    Question 10 : "Comment optimiser une application React qui charge et interagit lentement ?"

    La réponse décevante : une liste de tactiques hétéroclites — mémoïsation, chargement différé, segmentation des bundles — sans aucun cadre conceptuel.

    La réponse qui se distingue : « Je commencerais par mesurer plutôt que de deviner. Le Profiler des React DevTools et le panneau Performance des Chrome DevTools vous indiquent si le goulot d’étranglement réside dans le temps de chargement, le temps de rendu ou les deux — et il est inutile d’optimiser à l’aveugle. »

    En ce qui concerne le chargement :

    • Décomposition du code : La décomposition basée sur les routes via React.lazy et Suspense constitue la base, mais cela ne devrait pas s’arrêter là. Les composants lourds qui ne sont pas immédiatement visibles — modaux, contenu en dessous de la zone visible — méritent également leurs propres points de décomposition.
    • Préchargement : Utilisez <link rel="preload"> pour les ressources essentielles, et associez React.lazy à des indications de préchargement pour les routes que l’utilisateur est susceptible de visiter ensuite.
  • Analyse des bundles : exécutez webpack-bundle-analyzer pour détecter les surcharges. Il est fréquent de trouver un bundle de 2 MB dont 1,5 MB proviennent d’une seule bibliothèque de visualisation que seule une page utilise réellement.
  • Shaking d’arbre : assurez-vous que les imports n’ont aucun effet secondaire et sont écrits sous forme de modules ES. Écrire import lodash from 'lodash' au lieu de import debounce from 'lodash/debounce' peut faire une différence de 100 KB dans votre bundle final.
  • En ce qui concerne les interactions :

    • Virtualisation : dès qu’une liste dépasse environ 50 éléments, optez pour react-window ou react-virtualized. Afficher 10 000 nœuds DOM en même temps ne sera jamais rapide, quel que soit le degré d’efficacité du reste de votre code.
    • Une stratégie de mémorisation disciplinée : Évaluez d’abord, puis agissez. Enveloppez les calculs coûteux dans useMemo, les fonctions de rappel coûteuses dans useCallback, et les composants qui se rérendent inutilement dans React.memo. Mémoriser tout par défaut sans évaluer l’impact réel ajoute généralement des surcoûts plutôt que de les réduire.
    • Colocalisation des états : Gardez les états aussi proches que possible du composant qui les utilise réellement. Lever les états vers un ancêtre commun simplement parce que cela semble plus ordonné entraîne des rérendus supplémentaires chaque fois que ces états changent.
    • Séparation des contextes : Lorsqu’un seul contexte mélange des mises à jour fréquentes — comme la position de la souris — avec des mises à jour moins fréquentes — comme l’état d’authentification — divisez-le en deux. Sinon, chaque mouvement de la souris force un rérendu de tous les composants qui en dépendent, y compris ceux qui ne s’intéressent qu’à l’authentification.

    Prestations perçues :

    • Les écrans squelette plutôt que les indicateurs de chargement donnent l’impression qu’une interface est plus rapide, car le contenu semble s’afficher progressivement plutôt que d’apparaître d’un coup.
    • L’hydratation progressive grâce aux limites Suspense de React 18 permet à l’ contenu essentiel d’être chargé en premier, tandis que les sections secondaires le sont ensuite.
    • L’indicateur Interaction to Next Paint, un nouveau critère de Core Web Vital de Google, mérite d’être suivi. Il remplace First Input Delay car il mesure la réactivité tout au long du cycle de vie de la page et non seulement lors de la première interaction. L’objectif est que les gestionnaires d’événements s’exécutent en moins de 200 millisecondes.

    Lectures complémentaires

  • Dix flux Power Automate permettant des économies de temps hebdomadaires mesurables — Découvrez dix workflows pratiques de Power Automate, allant de l’extraction de données PDF au routage des approbations, qui permettent d’économiser des heures de travail administratif répétitif chaque semaine.
  • Comment le DataLayer de GA4 détermine si vos analyses sont fiables — Explication du rôle du dataLayer dans la liaison entre les sites web et GTM vers GA4, des raisons pour lesquelles les événements bruts perturbent les rapports e-commerce, ainsi que des méthodes pour structurer et déboguer correctement les données envoyées.
  • Concevoir pour le cache Retour/Avant : Éligibilité, restauration et état — Découvrez comment le cache Retour/Avant du navigateur restaure des pages entières, ce qui l’empêche silencieusement de fonctionner, et comment gérer l’état restauré avec pageshow et pagehide.
  • Six techniques TypeScript qui transforment les types en véritable prévention des bogues — Apprenez comment satisfies, les unions étiquetées, never checks, unknown, les types dérivés et les IDs marqués permettent à TypeScript de détecter des bogues réels au moment de la compilation plutôt qu’en production.
  • Six features natifs HTML qui remplacent les librairies UI JavaScript courantes — Découvrez comment popover, exclusive details, dialog, Declarative Shadow DOM, fetchpriority et datalist remplacent le JavaScript personnalisé, ainsi que les limites qu’ils présentent encore.