Fermer

juin 1, 2021

Pourquoi mon application React estelle lente ? — fracassant


À propos de l'auteur

Drew est un ingénieur d'état-major spécialisé en frontend chez Snyk ainsi que co-fondateur de Notist et le petit système de gestion de contenu Perch. Avant cela, …
En savoir plus sur
A dessiné

Dans cet épisode, nous parlons de la performance de React. Quels facteurs ralentissent nos applications React et comment pouvons-nous y remédier ? Drew McLellan s'entretient avec l'expert Ivan Akulov pour le savoir.

Dans cet épisode, nous parlons des performances de React. Quels facteurs ralentissent nos applications React et comment pouvons-nous y remédier? J'ai parlé à l'expert Ivan Akulov pour le savoir.

Afficher les notes

Mise à jour hebdomadaire

Transcription

Photo d'Ivan AkulovDrew McLellan : C'est un développeur Google expert, ingénieur logiciel full-stack et consultant en performance, et il est le fondateur de l'agence de performance web, PerfPerfPerf. Il passe une grande partie de son temps au cœur de JavaScript et a contribué à différents projets open source, souvent axés sur la performance. Nous savons qu'il connaît son métier en matière de performances Web, mais saviez-vous qu'il a déjà sauvé un panda d'un toit en utilisant uniquement un pogo stick ? Mes formidables amis, bienvenue, s'il vous plaît, Ivan Akulov. Salut Ivan. Comment allez-vous ?

Ivan Akulov : Smashing. Merci.

Drew McLellan : Je voulais vous parler aujourd'hui des performances Web, car c'est votre objectif professionnel et votre domaine d'expertise. Mais en particulier, sur les performances avec React. Quelle part de votre travail implique de travailler avec un framework réactif tel que React ? Est-ce quelque chose qui devient de plus en plus courant ?

Ivan Akulov : Ouais. Je pense que c'est 50-50. Je pense que la moitié de mon travail est consacrée à aider les clients avec des performances nettes faibles et une autre moitié de mon travail est consacrée à aider les clients avec les performances d'exécution de React.

Drew McLellan : Est-ce que cela augmente ? Cet équilibre augmente-t-il ? Voyez-vous plus de clients adopter React par rapport aux méthodes traditionnelles ou à d'autres frameworks ?

Ivan Akulov : Eh bien, pour être honnête, il est difficile de comparer React avec d'autres… Il y a deux manières de répondre à cette question. Le premier est de savoir si React devient plus populaire que les bibliothèques traditionnelles comme les bibliothèques JavaScript, jQuery, etc. C'est certainement vrai. Cela dure depuis un moment. Un autre est de savoir si React, comme direct brut ou faux par rapport à Vue et à d'autres frameworks.

Ivan Akulov: Pour être honnête, non. C'est vraiment difficile de juger de mon côté. Ce que je sais, c'est que React semble définitivement être le framework le plus populaire. De plus, j'ai quelques amis de différentes parties du monde et ce n'est en fait pas vrai pour différentes zones géographiques. Par exemple, en Géorgie, qui est le pays, pas l'État américain. Autant que je me souvienne, la plupart des développeurs locaux utilisent Angular, et c’est assez intéressant. Je suis venu une fois pour faire une conférence sur React, et les personnes qui organisaient l'événement m'ont dit qu'il serait plus difficile de trouver des participants parce que React n'est pas très populaire auprès d'eux.

Drew McLellan : C'est vraiment intéressant. . SI quelqu'un venait te voir et te dire: «Hé Ivan, tu es un bel homme. Pourquoi mon application React est-elle lente ? » Où commenceriez-vous à chercher ? Existe-t-il les principaux types de problèmes rencontrés par les développeurs lorsqu'il s'agit de React ?

Ivan Akulov : Ouais. Lorsqu'un développeur vient me voir et me demande : « Hé, mon application est lente. Pourquoi cela se produit-il ? Comment pouvons-nous l'approuver ? » Ma première étape serait de reproduire cela localement. Lorsque je reproduisais cela localement, j'enregistrais à partir des outils de développement, du profil de performance et du profil de performance React DevTools. Ce seraient donc mes deux principaux outils.

Drew McLellan : Vous avez mentionné les outils de profilage React, que vous disent ces outils ? Vous disent-ils, par exemple, quels composants sont lents dans votre application ?

Ivan Akulov : Ouais. Ma première étape serait d'examiner les React DevTools. React DevTools a deux types. Ils ont l'onglet de l'arborescence des composants, qui sont évidemment tous les composants que vous avez sur l'application, évidemment. Il existe également un onglet appelé profileur, qui vous permet d'enregistrer le profil du rendu de l'application, comme le nombre de rendus, les composants qui prennent le plus de temps à chaque rendu.

Ivan Akulov : Ma première étape serait être de reproduire ce problème avec lequel le développeur m'est venu. Enregistrez un profil en session à l'aide du profileur React, puis examinez ce qui se passe exactement. En règle générale, il y a deux problèmes principaux qui rendent ce lent, deux fruits à portée de main sur lesquels vous devriez vous concentrer en premier.

Ivan Akulov: Le premier concerne les composants qui prennent trop de temps à être rendus et qui peuvent être pour de multiples raisons. Il n’y a peut-être qu’un seul composant qui fait quelque chose de cher. J'avais un client qui… Eh bien, c'est essentiellement le client qui était un site statique rendu via React. Ce qu'ils faisaient, ils se connecteront aux articles du serveur, au format démarque. Et puis ils ont analysé cette démarque en HTML. Ils convertissaient cette démarque en HTML sur le client, car l'article est très volumineux et prenait quelques 100 millisecondes. Ce composant unique de l'analyse des articles prenait quelques 100 millisecondes pour être rendu. C'est un exemple.

Ivan Akulov : En plus d'un seul composant lent, il pourrait y avoir juste des sous-tableaux de composants rendus inutilement et être un goulot d'étranglement. Une autre chose qui se produit est la cascade de rendus. C'est à ce moment-là que vous effectuez une seule action dans l'application, et cela programme quelques rendus les uns après les autres. Donc, là encore, il pourrait y avoir un tas de raisons à cela. Il y a beaucoup de façons qui pourraient arriver. C'est une autre chose que j'examinerais et j'essaierais de réduire le nombre de rendus ou de déplacer les rendus inutiles programmés par React.

Drew McLellan : Y a-t-il des choses que vous pouvez faire dans la conception d'un Apple, la conception de une page en termes traditionnels pour vous assurer que vous ne rencontrez pas ce genre de problèmes de performances ?

Ivan Akulov : Dans la conception, vous voulez dire l'interface utilisateur/UX, n'est-ce pas ?

Drew McLellan : Oui, dans l'interface utilisateur. Existe-t-il des sortes de pièges communs faciles à tromper qui feraient une page, pourraient provoquer des rendus inutiles ou des choses comme ça?

Ivan Akulov: Je ne suis pas sûr. Je ne peux penser à rien pour le moment.

Drew McLellan: J'ai eu un problème, pas dans React, mais dans Vue. Je suis un ingénieur React en convalescence. Je travaille principalement dans Vue maintenant. J'ai traité certaines pages où j'avais une grande liste de données, et chaque ligne de la liste était un composant qui était rendu, et cette page pouvait contenir 1 000 éléments dans certains cas. Vous obtenez ce composant un rendu 1 000 fois. Dans des situations comme celle-là, existe-t-il des moyens de l'architecturer différemment pour que ce ne soit pas un problème ?

Ivan Akulov : Exact. Oui. Il existe différentes manières de le résoudre. Je ne peux appeler la solution pour cela que lorsque vous avez une table avec un grand nombre de lignes ou de colonnes, ou du moins avec un grand nombre de lignes, c'est la virtualisation, qui consiste essentiellement à prendre une bibliothèque de React. Nous devons faire un React virtualisé et vous avez la liste avec.

Ivan Akulov: Ce que fait la bibliothèque, c'est qu'elle utilise l'intersection de votre API pour trouver quels composants sont hors écran, quels composants sont activés. écran, et il rend sur les composants qui sont à l'écran. Si vous avez une liste de, disons, 1 000 éléments, mais que vous pouvez à tout moment supprimer la liste de 10 éléments, alors cette bibliothèque s'assurera que seuls 10 de ces bons éléments sont rendus dans le DOM. Vous obtenez un arbre DOM beaucoup plus petit, ce qui facilite les calculs stellaires, ce qui facilite les recalculs de mise en page avec un tas d'autres choses. Vous obtenez également une arborescence de composants React plus petite, ce qui facilite la réconciliation de React et des éléments similaires.

Ivan Akulov: Maintenant, l'API pour cela, qui fonctionne un peu différemment, mais qui est peut-être orientée vers le marché. Il s'agit de l'API de visibilité du contenu récemment introduite. Il s'agit donc d'une propriété CSS qui a été ajoutée dans les navigateurs, dans Chrome il y a six mois ou un an. Ce qu'il fait, c'est essentiellement la même chose que ces bibliothèques. Cependant, ce qu'il fait en pratique, c'est qu'il s'assure que les réseaux hors écran ne sont pas rendus. Ainsi, le navigateur les ignore ou [ignoring 00:08:10] complètement.

Ivan Akulov : Cela permet également de réduire considérablement les coûts de rendu. Cela ne va pas aider à réduire le React sur un [dream coast 00:08:21]. React réconcilierait toujours l'ensemble de l'arbre et organiserait les anciens nœuds pertinents de 1 000 composants. Mais si votre partie chère réside dans le rendu du navigateur et non dans le rendu direct, alors cela va vous aider.

Drew McLellan: Cela semble prometteur, et c'est une API de navigateur native, n'est-ce pas, plutôt qu'une partie de réagir ?

Ivan Akulov : Oui, exactement. C'est une propriété CSS unique. Il y a en fait deux propriétés CSS. La première propriété est appelée [low trail 00:08:46] content-visibility. Et le second, je pense, contient-hauteur-intrinsèque, contient-largeur-intrinsèque, donc deux propriétés.

Ivan Akulov: La ​​partie complexe, la chose complexe à propos de… En fait, la chose difficile à propos des deux contenus visibilité et à propos de la virtualisation est que vous ne pouvez pas vraiment le faire si vos éléments de liste ont une hauteur dynamique ou une largeur dynamique, si c'est du moins la raison. Ou en fait, vous ne pouvez pas le faire. Le navigateur ne peut pas connaître la hauteur et la largeur d'un élément à moins que vous n'essayiez de le réduire. Gagnez soit l'approche de virtualisation, soit l'approche de visibilité du contenu.

Ivan Akulov : Le problème est que si vous avez des articles avec une largeur de course ou si nous avons une hauteur de course, et que vous ne connaissez pas leur hauteur, c'est sûr , alors les virtualiser va être difficile, car la barre de défilement sauterait tout le temps pendant que vous faites défiler cette liste, car le navigateur rendrait cet élément, rendrait ce poids et ajusterait la hauteur de la page. C'est le défi de ça.

Drew McLellan : C'est toujours un défi classique avec la présentation des choses sur le Web, n'est-ce pas ? Savoir quelles sont les hauteurs avant qu'elles ne soient rendues, même jusqu'à des images et des choses comme ça.

Ivan Akulov : Ouais.

Drew McLellan : L'une des principales différences, s'appuyer sur un cadre comme React par rapport à la création de HTML et CSS, sorte de pages rendues côté serveur standard, vous avez en quelque sorte cet équilibre entre les performances de chargement et les performances d'exécution. Y a-t-il un moyen? L'un d'eux est-il plus important que l'autre ? Devriez-vous optimiser pour qu'un site soit performant une fois qu'il a terminé son chargement initial? Ou la priorité de chargement est-elle plus importante pour empêcher les visiteurs de partir avant même que les choses ne soient chargées? Ou est-ce un équilibre entre les deux ?

Ivan Akulov : Cela dépend vraiment. Mon opinion est que cela dépend vraiment du genre de chose que vous faites. Si vous êtes un site statique, ou si vous êtes un site ou une application, ou quelque chose qui doit être optimisé pour, par exemple, le référencement ou la diffusion d'annonces dans ce classement et ce coût publicitaire, les performances de chargement seront également plus importantes. , car c'est sur cela que le classement de recherche est basé. C'est sur quoi sont basés les coûts publicitaires.

Ivan Akulov : Et si vous faites des choses, si vous êtes une application complexe d'une seule page, à laquelle les utilisateurs viennent et font des choses pendant un certain temps. Je sais, vous êtes un éditeur graphique, vous êtes un peu n'importe quoi, vous faites des choses complexes avec JavaScript, puis les performances des tendances sont peut-être beaucoup plus importantes, car c'est en fait beaucoup plus difficile à mesurer. L'effet de cela est beaucoup plus difficile à mesurer.

Ivan Akulov: Je pense que les performances d'exécution sont beaucoup plus importantes ici, car c'est ce que les utilisateurs … Parce que c'est ce qui affecte la satisfaction globale des utilisateurs. Et si vous êtes lent, les utilisateurs vont laisser l'application aux concurrents et vont se plaindre auprès de vous. En fait, c’est une façon de mesurer cela.

Drew McLellan: Avec les applications à une seule page, existe-t-il une manière significative d’évaluer les performances des différentes parties de l’application? Supposons que cette partie de notre application est lente, ou cette partie de notre application est lente, et cette partie est correcte. Je veux dire, traditionnellement, nous regardons les pages pour voir comment elles fonctionnent. Mais dans une application d'une seule page, ce que vous chargez n'est pas seulement une page, c'est en fait vous échafaudez un cadre entier pour accéder à ce rendu initial. Existe-t-il un bon moyen d'aborder la mesure des performances sur l'ensemble d'une application ?

Ivan Akulov : C'est une bonne question. Il y a plusieurs façons d'aborder cela. Ainsi, le premier moyen est le plus simple, mais ce n'est probablement pas souvent ce que vous recherchez. Une chose que vous pouvez faire est que vous pouvez utiliser l'API de navigateur intégrée pour collecter des données [core web vitals 00:12:55] et collecter ces données et les enregistrer quelque part comme dans le [analytics 00:13:02] ou un autre stockage, puis agréger ces données et examiner votre première entrée. retard, votre décalage cumulatif de mise en page tout au long du rendu de l'application, etc. C'est un examen de très haut niveau, et ce ne sera peut-être pas ce que vous recherchez.

Ivan Akulov : Si Je faisais ça, ce que je ferais probablement, c'est que je me concentrerais sur les spécificités de mon application. Donc, disons que mon application est un éditeur de texte. Ensuite, ce qui compte vraiment pour moi, c'est que très peu de métriques utilisateur qui comptent vraiment pour moi, c'est la latence d'entrée. Plus le texte est rendu rapidement après avoir appuyé sur une touche, meilleures sont les performances. Il existe peut-être quelques autres mesures telles que le basculement entre différents menus ou l'application d'un formatage comme le gras ou l'italique, etc.

Ivan Akulov : Ce que je ferais dans ce cas, c'est que j'essaierais de mesurer la durée de chacun des ces interactions. J'essaierais de mesurer la latence d'entrée, la durée des rendus entre j'appuie sur la touche et entre la touche apparaît sur la durée de l'écran comme l'application du style gras, etc. J'essaierais de collecter ces métriques dans n'importe quel vrai logiciel de surveillance des utilisateurs , et j'y regarderais pour savoir si je suis rapide ou lent, ou si je deviens plus rapide ou si je deviens plus lent.

Drew McLellan : S'agit-il plutôt de mesurer les choses avec laquelle vos utilisateurs interagissent peut-être, plutôt que de regarder une page et de dire à quelle vitesse cette page, parce que cela n'a pas vraiment de sens quand vous avez une interface plus interactive?

Ivan Akulov: Ouais, exactement. J'ai entendu à plusieurs reprises que pour certaines applications complexes, le temps de connexion n'est en fait pas un problème car les utilisateurs sont habitués à… Lorsque vous ouvrez un Photoshop, votre utilisation de ce Photoshop prend un certain temps à charger. Vous avez l'habitude de voir cet espace réservé de chargement. Ce n'est certainement pas un problème lorsque vous ouvrez, disons, Google… Google Sheets n'est pas le bon exemple, mais n'importe quel logiciel de dessin Web. Encore une fois, cela prend un certain temps à charger, c'est bien. C'est bien tant que cela fonctionne réellement rapidement après cela. Si le chargement prend un certain temps mais que cela fonctionne rapidement après cela, alors les utilisateurs ne vont pas se plaindre, car ils sont habitués à ce comportement.

Drew McLellan: Vous avez mentionné le délai d'entrée pendant que vous tapez . J'ai vu un de vos tweetstorm où vous avez abordé le sujet des composants qui semblent réagir trop lentement, comme taper dans un champ de texte et que les lettres mettent du temps à apparaître. C'est évidemment un problème de performances, car sur une page Web ordinaire, la saisie dans un champ de texte est instantanée. Alors, qu'est-ce qui cause ce genre de ralentissements ?

Ivan Akulov : Tout comme avec une performance correcte générique, il y a beaucoup de choses qui pourraient causer cela. Ce qui se passe généralement lorsque vous tapez dans un champ de texte et qu'il faut un certain temps pour rendre cette touche que vous venez d'appuyer, c'est que vous exécutez trop de JavaScript lorsque vous gérez cet événement. Et il pourrait y avoir plusieurs raisons à cela. Vous pourriez rendre trop de composants. Peut-être que vous appuyez sur la touche, et cela enregistre l'état de la saisie de texte dans le magasin Redux. Et cela nous donne toute l'application à rendre, car je sais que cela invalide une grande partie de ce magasin Redux.

Ivan Akulov: Ou peut-être que vous planifiez quelques rendus les uns après les autres. Ou peut-être existe-t-il une bibliothèque tierce qui a mis du temps à recalculer quelque chose. Vraiment, il n'y a pas de réponses uniques. En fait, les performances de rendu sont vraiment un défi pour moi. Je pense en général à cette partie.

Ivan Akulov : Les performances de chargement sont beaucoup plus faciles à profiler, c'est beaucoup plus facile à analyser, c'est beaucoup plus facile à mesurer. Je pense que nous voyons réellement l'effet de cela, et qu'il y a beaucoup plus de contenu sur les performances de chargement, beaucoup plus d'outils pour les performances de chargement. Il est beaucoup plus facile à mesurer et à profiler dans la mesure où il est à peu près identique pour chaque application. Quelle que soit l'application, peu importe ce dans quoi elle est écrite, peu importe le type de choses qu'elle fait, elles se chargent toutes plus ou moins de la même manière. Quelle que soit l'application, vous pouvez toujours vous concentrer sur les mêmes choses, et vous pouvez enseigner les mêmes choses aux gens, et ce serait bien.

Ivan Akulov : Alors qu'avec les performances d'exécution, les spécificités des ralentissements et les défis de temps d'offre spécifiques sont très différents avec chaque application. Ils pourraient être optimisés pour certaines choses de base, mais il est très difficile d'en parler à un niveau supérieur, car avec chaque application, ils sont différents avec chaque application.

Ivan Akulov : En fait, l'un de mes les défis qu'ils espèrent résoudre avec la version que je fais est de donner une sorte d'introduction de niveau assez élevé aux performances d'exécution pour que les personnes qui assistent à cet atelier puissent apprendre qu'il peut l'appliquer à leurs applications avec leurs défis spécifiques, et avec leur logique métier spécifique.

Drew McLellan : S'il y a des choses que vous devez être particulièrement interactives et répondre très rapidement en termes de rendu, disons, pour reprendre notre exemple, encore une fois, de taper dans un champ de texte, et il y a un autre travail à faire qui est inévitable. Existe-t-il un moyen de prioriser l'un par rapport à l'autre dans React ? Pouvez-vous dire : « Je dois faire ce rendu ? » Et puis, une fois que c'est terminé, nous faisons maintenant toute cette mise à jour de l'état. Est-ce possible ?

Ivan Akulov : Bien sûr. Oui. Il y a, encore une fois, plusieurs façons de le faire. Le premier est celui sur lequel React travaille depuis un certain temps, qui est le mode simultané et la hiérarchisation des choses qui se produisent sur cet écran par rapport à celles qui se produisent sur cet écran, etc., etc. Je vais être honnête, je ne Je n'ai pas encore beaucoup de connaissances à ce sujet. Principalement parce qu'il ne s'est pas stabilisé. C'est bien de savoir à ce sujet et j'aime lire à ce sujet, mais je ne pense pas qu'il soit logique de l'enseigner encore, car ce n'est pas quelque chose que vous pouvez prendre et appliquer maintenant, mais cela pourrait beaucoup changer avant sa sortie. au public.

Ivan Akulov: Lorsque React publiera finalement le mode simultané et toute la priorisation, ce sera probablement la réponse universelle ou l'une des meilleures réponses. Jusque-là, ce que nous pourrions faire, c'est retarder les calculs en effectuant des ralentissements ou en avançant, ou en transférant des calculs coûteux aux travailleurs Web. Ou si les travaux coûteux ne passent pas par JavaScript, mais par les styles [reconfiguring 00:20:19] et la reconfiguration de la mise en page, ce qui est en fait un problème très courant dans certaines applications lorsque vous manipulez avec le DOM, et cela finit par provoquer les premiers calculs, puis peut-être les optimiser problèmes.

Ivan Akulov : Ouais. Si nous avons un éditeur de texte et que nous devons nous assurer que nous le tapons rapidement, ce que je ferai, c'est que j'essaierai de le faire, ou sur le moins de code possible à chaque pression de touche. Et tout ce qui pourrait être retardé, essayez de le retarder de quelques 100 millisecondes, ou peut-être de quelques secondes pour vous assurer qu'il ne s'exécute que lorsque l'utilisateur a fini de taper. C'est comme une vue d'ensemble de haut niveau. Encore une fois, les détails dépendent vraiment de l'application. Donc, il pourrait y avoir de meilleures solutions architecturales, mais c'est par là que je commencerais, ou ce serait ce que j'examinerais en premier.

Drew McLellan : Parce qu'avec chaque bit de JavaScript que nous ajoutons à une application, il y a un potentiel pour qu'il devienne de plus en plus lent et de plus en plus lent. Y a-t-il un moyen de récupérer cela? Est-il possible pour une application React d'avoir un score Lighthouse parfait, par exemple ?

Ivan Akulov : Ouais. C'était en fait quelque chose. Ouais, pour en revenir au texte, juste une chose que j'ai oublié de mentionner est que s'il y a un seul composant isolé, dont les performances sont super critiques et que nous ne pouvons pas le faire rapidement avec reg, alors une chose que je ferais peut-être essayer de le faire fonctionner sans React du tout. Donc, le faire fonctionner avec la manipulation directe du DOM et du JavaScript simple et des trucs comme ça.

Ivan Akulov: La ​​raison en est que si React est excellent en termes de maintenabilité, comme la raison pour laquelle nous sommes passés de jQuery à React était que React nous permet d'écrire un code qui est beaucoup plus maintenable, beaucoup plus facile à prendre en charge. Il est également beaucoup plus facile d'introduire accidentellement des goulots d'étranglement majeurs avec React. Vous pourriez accidentellement rendre l'application entière ou vous pourriez accidentellement avoir un composant qui rend assez fréquemment il fait des choses coûteuses.

Ivan Akulov: Si vous passez à ce composant spécifique en JavaScript brut, alors les chances que cela se produise accidentellement ralentir serait bien inférieur. Pour en revenir au score Lighthouse, c'est en fait l'approche que nous avons adoptée avec le site 3perf.com. J'ai couru depuis cette agence de conseil, et elle a son propre site. Donc, j'ai vraiment mis à niveau ce site à Gatsby, simplement parce que je voulais essayer cette pile et cela semblait bien, alors je l'ai fait. Et cela a très bien fonctionné en général, à part une chose, qui est la partition de Lighthouse.

Ivan Akulov: J'ai construit cela sur Gatsby et déployé pour amplifier et m'assurer que le site se charge rapidement ou se rende rapidement. Mais le score Lighthouse était mauvais en raison du temps de réaction et des mesures du temps de travail. Alors que le site s'affichait rapidement, il chargeait ensuite un énorme paquet JavaScript, et ce paquet JavaScript s'exécutait et prenait un certain temps à s'exécuter, prenant un certain temps pour rendre la même page que l'utilisateur voit déjà.

Ivan Akulov. : Une chose que j'ai faite a été de jeter un poids de JavaScript que mon site utilisait. Dans mon cas, c'était assez facile à faire, car il n'y avait presque pas de JavaScript. Il n'y avait que quelques éléments interactifs, et je les ai remplacés par des scripts en ligne, et cela a très bien fonctionné. J'ai opté pour le JavaScript. Il existe des plugins Gatsby pour cela, comme le plugin Gatsby, pas de JavaScript. Ce fut l'une des victoires les plus importantes en termes de point de chargement. Donc, je pense que mon score Lighthouse est passé de 60 quelque chose à 90 quelque chose grâce à ce seul cas.

Ivan Akulov : En fait, j'ai un ami qui s'appelle Andrei [Signik 00:24:11]. C'est un ingénieur front-end. Il est assez connu dans la communauté front-end russe. Et Andrei est connu pour le fait qu'il préconise fortement d'utiliser moins React. Fondamentalement, chaque fois que vous ouvrez Twitter et chaque fois que vous voyez une conversation sur la lenteur de React, vous pouvez souvent le voir mentionner que : « Hé, vous n'avez pas du tout besoin de React sur ce site, car c'est un site statique. Pourquoi utilisez-vous React ici ? Utilisez simplement de bonnes vieilles technologies Web et ce sera beaucoup plus rapide. Parce que vous n'avez pas besoin de React sur le client. »

Ivan Akulov : Je dirais que je suis d'accord avec lui. Il y a beaucoup de cas où React est pratique pour l'expérience de développement, et je soutiendrais totalement son utilisation pour… Il y a beaucoup de cas, y compris les sites statiques où React est pratique pour l'expérience de développement, mais cela ne signifie pas qu'il doit être servi à l'utilisateur. Une chose que vous pouvez faire est d'utiliser React sur le serveur. Utilisez-le pour définir le moteur de modèle, en gros, mais ne le diffusez pas au client. Si vous pouvez le faire, ce serait l'une des meilleures choses que vous puissiez faire en matière de performances de chargement.

Drew McLellan : Donc, votre meilleur conseil pour les performances est de vous débarrasser de tout JavaScript ?

Ivan Akulov: Astuce pour le React, où vous devriez vous débarrasser de React. Oui.

Drew McLellan : L'une des choses que vous entendez avec les personnes qui adoptent un cadre comme React, c'est que cela peut être fait pour des raisons de performances. Il est beaucoup plus facile de créer une expérience asynchrone et d'obtenir des performances perçues plus rapidement si vous disposez d'un cadre puissant gérant votre état, plutôt que de vous fier à une page rendue par un serveur, par exemple, pour compiler une page complète en une seule fois. Vous pouvez charger dans un framework, puis le remplir de manière asynchrone.

Drew McLellan : De l'autre côté, vous avez des personnes qui avertissent que leurs expériences sont qu'une grande application React peut être très lente et peut être vraiment nuisible à la performance. Avec toutes choses, probablement, cela dépend de ce que vous faites. Mais y a-t-il un moyen de juger si votre utilisation sera bonne ou mauvaise pour les performances ?

Ivan Akulov : C'est une bonne question, pour être honnête. Je n'ai pas entendu parler de cas. Cela pourrait être totalement peut-être que mon point de vue est faussé parce que je travaille généralement avec des applications lentes, pas avec des applications rapides. Mais je dois être honnête, je n’ai pas entendu parler de cas où les gens passeraient à React car il est plus rapide que l’approche initiale. Les gens changent définitivement parce qu'il est plus pratique d'ouvrir deux fois, ou parce qu'il est plus facile d'écrire des codes maintenables, ou parce que l'écosystème est plus grand, ou quelque chose comme ça. Mais j'ai entendu parler de cas de changement parce que c'est plus rapide.

Ivan Akulov: En fait, la vitesse était une chose qui était fortement encouragée à l'époque de la création de React, comme tout le groupe, [Rachel Dolphin 00:27:13]etc., etc. Mais React, quelques années après l'introduction de ce mode, React l'a abandonné, car ils se sont orientés sur l'expérience de développement. Je ne suis pas vraiment sûr de ce qu'ils font, mais je me souviens qu'ils ont abandonné ce modèle parce que ce n'était plus ce pour quoi les gens achetaient React.

Drew McLellan : Probablement, React sera toujours un peu plus lent que le traditionnel, mais il comporte également de nombreux avantages en termes d'expérience de développement et de code maintenable.

Ivan Akulov: Je pense que oui. Jeff Edwards a un excellent article qui s'appelle, Our Pit of Success, ou quelque chose comme ça. Et dans l'article, il mentionne que les langages de programmation et les écosystèmes ont un terme de puits de succès. Par exemple, C ++ a un gouffre de succès, ou un gouffre de désespoir de problèmes de mémoire. Chaque fois que vous écrivez du code en C++, il est très facile d'écrire du code qui effectue un accès direct à la mémoire, et ils introduisent des bogues, des vulnérabilités ou autre.

Ivan Akulov : Vous devez continuer à réfléchir. , vous devez constamment réfléchir pour vous assurer que vous n'écrivez pas le code qui introduit des problèmes de mémoire, qui introduit des bogues de mémoire. Je pense au JavaScript, le gouffre unique du succès ou le gouffre du désespoir. Le système JavaScript et React présente de nombreux avantages. Encore une fois, c'est la maintenabilité, c'est tout ce dont nous avons parlé.

Ivan Akulov: Je pense qu'un gouffre de désespoir est un piège dans lequel il est trop facile de tomber, à moins que vous ne réfléchissiez activement, et à moins que vous ne soyez vous empêcher activement de tomber dessus, c'est créer une application qui ralentit soit en termes de performances de chargement. Parce qu'il est trop facile d'installer une dépendance NPM et de l'importer dans l'ensemble et de la subdiviser en 100 kilo-octets ou 185 kilo-octets dans un ensemble. Ou en termes de performances de retour, car il est trop facile de créer un composant qui s'afficherait au fil du temps et exécuterait beaucoup trop de codes ou autre.

Drew McLellan : J'ai découvert votre travail pour la première fois il y a environ un an lorsque vous avez posté une étude de cas analysant les performances d'une page Notion. Je pense que nous aimons tous Notion, et il n'y a probablement pas une personne qui ne souhaite pas que ce soit plus rapide. ne pensez pas que ce n’était pas un travail rémunéré, n’est-ce pas? C'était juste un exercice pédagogique ?

Ivan Akulov : Ouais. Parfois, lorsque j'ai le temps d'essayer de faire des études de cas pour certains sites populaires, j'aime énormément le faire. C'est aussi un excellent matériel pédagogique pour quiconque le trouve utile.

Drew McLellan: Et est-ce le genre de processus que vous suivez lorsque vous commencez une évaluation des performances des applications? Est-ce que l'étude de cas avec Notion suit le même genre de processus que vous suivriez pour quoi que ce soit ?

Ivan Akulov : Ouais. Le processus [Tyler Wilford 00:30:21] consiste à identifier un problème, à reproduire un problème localement. Dans le cas de Notion, la page Notion a mis un certain temps à se charger, puis vous la profilez avec tous les outils dont vous disposez et essayez de trouver des fruits bas ou pas si bas. Essayez de comprendre comment couper ce fruit. Donc, c'est l'examen de haut niveau. Il y a beaucoup de détails.

Drew McLellan : C'était une lecture très fascinante, et je mettrai un lien vers cela dans les notes de l'émission afin que les gens puissent aller le regarder s'ils ne l'ont pas fait. vu. J'ai vu que vous aviez mentionné que React 17 avait supprimé l'une de vos fonctionnalités de performance préférées l'année dernière. De quoi s'agissait-il ?

Ivan Akulov : React a traversé plusieurs générations de fonctionnalités de performance. Comme React 15, je pense que jusqu'à 15.5 avait un objet puissant intégré qui vous permettait de mesurer les composants les plus chers ou les composants rendus inutilement. Vous auriez pu écrire dans la console quelque chose comme perf dot… Je ne me souviens pas du guide concret. C'était comme mesurer quelque chose.

Ivan Akulov:Oui, l'idée était que, c'était assez pratique pour la détection, quels composants rendaient inutilement. Je vois dans quels composants sont rendus, mais l'arbre DOM résultant était identique à l'arbre DOM précédent. Mais ensuite, React a supprimé cela. Je ne sais pas pourquoi. Je ne me joignais pas activement à la performance à l’époque.

Ivan Akulov: React a supprimé cela. Je pense qu'ils ont également introduit le profileur React à l'époque. Mais aussi, à un moment donné, ils ont introduit une API différente, qui était le timing de l'utilisateur. L'idée était que chaque fois que vous exécutez la version de développement de React et que vous enregistrez une trace des performances avec l'onglet de performances Chrome DevTools. What React would do is it would measure, it would mark the beginning and the end of each components, when each component renders and when each component effects run, like componentDidMount, componentDidUpdate.

Ivan Akulov: So, it would measure the beginning and the end of each of these components, and it’s lifecycle hooks. And it would part put them into the performance recording using the user timing API. This was super convenient for debugging, because when you record a performance recording of a single render or whatever, and you open the main thread pane, and you look into it, what you would see is you would see a lot of wrecked internal code, like its fiber algorithm working on the components, calling array component.

Ivan Akulov: It would be super hard to identify where each component rendering starts, where each component rendering ends. But if you scroll a bit higher and open the user timing session that you would be able to see that straight ahead, and you would be able to match what’s happening in the user timing app scene, which component is rendering right here to what’s happened in the performance pane. If you see some [inode 00:33:30] expensive salary calculation of the performance pane, you would be able to just scroll a bit higher and see that, “Hey, this matches this specific component or this specific inode, componentDidMount virtually.”

Ivan Akulov: So, this was super convenient for debugging, like particular performance issues. However, the problem with this was that for React developers, it was fairly hard to maintain. There was a GitHub discussion with the description, with the particular reasoning. What React ended up doing was they removed this API in React 17. Removed this future in React 17.

Ivan Akulov: So, right now in React 17, the only way to debug React performance is to use the React profiler. While this works great for a lot of things, there are a few use cases like seeing lifecycle hooks, which React profiler doesn’t measure or my chain. Figuring out why a specific component takes a while to render, which again, React profiler shows you that this specific components takes 30 or 300 milliseconds to render, but it doesn’t show why and to figure out why you have to switch back to the performance pane.

Ivan Akulov: So, with user timings, that was easy to match a specific component to what’s happening inside of that component, and without user timing, with just the React profiler that’s actually harder. It’s a pity it get removed.

Drew McLellan: How are things looking for the future of performance with React? Do you know of any features and changes that are coming that might help?

Ivan Akulov: Yeah. There are two things that I’m looking forward to. I think the one is the concurrent mode, which lets React prioritize some stuff over another stuff. I think defer was happening of this screen. I haven’t been really following the development. I know that it’s mostly close to [scene 00:35:31]. It could take another year, perhaps, but it’s fairly close to getting released.

Ivan Akulov: Another thing is the recently introduced theme, which is React server components. That’s actually the thing I’m really looking forward to. So there are two areas where React apps may be slow. The one is the runtime performance, and the other is loading performance. And loading performance is not only about the huge bundle and etc, etc, which everyone is talking about. But it is also about the bundle execution, and more importantly, the React hydration process.

Ivan Akulov: So, whenever you have a React app that’s server-side rendered, and you serve that page to the client, and then a large React server act to that page, what React does is it gets through the hydration process. It gets all the DOM nodes that have been already ordered render. It reconstructs the virtual DOM tray, and it reattaches this … Or resource the relationship between its virtual DOM and the actual DOM nodes.

Ivan Akulov: The problem with its process is that this is the single most expensive process during page loading. IF you’re loading a page, and that page runs a few chunks of JavaScript, then that chunk of JavaScript is going to be the most expensive. It could easily take a few 100 milliseconds, or like a second on slower device. This means that for the whole second of the whole few 100 milliseconds, the page would not responsive. So, if the user tries to scroll it or interact with it during that time, then the page could just not respond at all.

Ivan Akulov: Yeah, hydration is typically, one of the most expensive things, and it’s hard to optimize, because React needs to hydrate all these components. There are only a few things that you could do with it today. One thing is partial hydration, which is, if you have some pieces of the site or of the app that you don’t need to rehydrate, which can stay static, but you could write a bit of code around that and bailout these subarrays from rehydration. If these subarrays are typically expensive, then not rehydrating them would save you a lot of time. But this is actually hard to do nowadays. There are a few libraries for that, but this is not a popular approach. It’s hard to do. We could do that, but it typically requires writing your own code around the subarrays.

Ivan Akulov: What server rendered components are going to do is they are going to take partial hydration. They’re basically going to introduce partial hydration and a bunch of other benefits in the code. So, taking back that example that we’ve talked about earlier, like a static site, which loads a huge pile of markdown from the server, and then converts it to HTML during hydration.

Ivan Akulov: One way to avoid paying that cost is to turn that component that converts markdown into HTML into server rendered component and do this conversion on the server, and serve the concrete HTML to the client. Ad that will save you a few 100 milliseconds of the markdown, if the markdown blob is large.

Ivan Akulov: I’m really looking forward towards React server components. So, they are going to be great for a lot of reasons, but also particularly for making hydration less expensive.

Drew McLellan: That sounds really good. You’ve got a workshop coming up at the end of May with Smashing. And this being 2021, of course, it’s all online. It’s called the React performance masterclass. What sort of things would an attendee expect to learn?

Ivan Akulov: My goal with this workshop is to take a few apps, a few example of apps that have the same issues that I see in client apps over and over again and again, and to show attendees, to walk attendees through … Actually, ask attendees to do the same optimization to their apps. But also to guide attendees and to walk attendees through my mindset, through my process, which I applied to solving to identifying and solving each of these specific problems.

Ivan Akulov: We’ll talk about issues like expensive renders, like when you have a component that takes a while to render, how to identify it, how to optimize it. We will talk about expensive effects like componentDidMount. If you use a glass component or if you use a functional component. We will talk about net server renders. What to do when you click a button and that causes the whole app to render, and that makes the app slow. We will talk about cascading renders when you’re scheduling a few renders in it all.

Ivan Akulov: We will also talk about hydration, and about operation, and what to do with expensive layout and stellar calculations, and how to identify them, how to fix them. That’s the problems I’m planning to show. Perhaps also something else if it fits. Well, we would also talk about bunch of solutions for that starting from partial hydration, which is for hydration going through ways to correct hooks and more advanced third-party libraries that help with optimizing net server renders and making the components render fast.

Ivan Akulov: We would walk through tools which help with detecting what specific color are rendered, white rendered. And we would also talk through solutions like virtualization or on the content visibility, CSS property, or other stuff. The CSS contained property, which is rarely used, and not really known trick, but it helps with performance optimization.

Ivan Akulov: We would also look at solutions like virtualization and content visibility. The content visibility, CSS property, and other stuff that helps with optimizing layout thrashing, optimizing expensive stellar calculations. That’s what I’m planning to talk about. But the primary focus would be on showing attendees the most common [departments 00:41:43]the most common issues that happened, and specific ways to identify them, to profile them and to fix them. So, that’s my goal.

Drew McLellan: It sounds like that, yes, you’re going to equip attendees with everything they need to identify and fix their own performance problems, which sounds really great. So, I’ve been learning all about React performance today. What have you been learning about lately, Ivan?

Ivan Akulov: One experience that I’ve been having lately is … I’ve been helping a client to optimize a large [conflict 00:42:19] point for their site. It’s actually not about React or performance of React. It wasn’t performance. They don’t use React at all. But the challenge is that we’ve done pretty much everything we could have done with their site like pretty much all the …

Ivan Akulov: We’ve got pretty much all the low hanging fruits. We’ve optimized everything that makes sense. The page is actually so large that the browser renders eight in steps. It renders. It parses it in steps. It parses a few 100 lines, then it renders these few 100 lines, and it parses the next few 100 lines, and renders these few 100 lines. It renders the header fields. It renders some parts of the main content field. After that, then it renders another part of the main content.

Ivan Akulov: What this ends up doing is this chunk rendering and pushing to large [conflict 00:43:06] point way higher than I would expect it to be if the browser rendered everything in one go. I don’t see any typical reasons that they typically see in apps that would push that large [conflict 00:43:20] point higher.

Ivan Akulov: Anyway, what I’m doing right now is I am going deep into Chrome internals and trying to figure out what exactly it does when it’s rendering that page and why exactly the chunked rendering is happening and what we can do to make sure it doesn’t happen. To make sure the page renders in one go. Actually, there isn’t learning experience for me. I just hope I don’t need to compile from scratch.

Drew McLellan: Let’s hope so. If you, dear listener, would like to hear more from Ivan, you can find him on Twitter where he’s at @iamakulov. And his personal website is iamakulov.com. His agency, Perf Perf Perf, can be found on the web at 3perf.com. And if you like to find out more about Ivan’s workshop on React performance, you can find all the information at smashingconf.com. Thanks for joining us today, Ivan. Do you have any parting words?

Ivan Akulov: Take care, be fast, and enjoy your life.

Smashing Editorial" width="35" height="46" loading="lazy" decoding="async(il)




Source link