Depuis son introduction initiale, React a changé la mentalité des développeurs front-end lors de la création d'applications Web. Avec Virtual DOM, React rend les mises à jour de l'interface utilisateur (UI) aussi efficaces que jamais, tout en rendant votre application Web plus précise. Mais pourquoi les applications Web React de bonne taille fonctionnent-elles toujours mal?
Eh bien, la clé est de savoir comment vous utilisez React.
Une bibliothèque frontale moderne comme Réagir cela ne rend pas votre application plus rapide comme par magie. Le développeur doit comprendre comment React fonctionne et comment les composants vivent à travers les différentes phases du cycle de vie des composants.
Avec React, vous pouvez bénéficier de nombreuses améliorations qu'il offre en mesurant et en optimisant le moment et le mode de retour de vos composants. Et React fournit uniquement les outils et les fonctions nécessaires pour rendre cela plus facile.
Dans ce didacticiel React, vous apprendrez comment mesurer les performances de vos composants React et les optimiser pour créer une application Web React plus performante et plus performante. De même, vous apprendrez comment quelques bonnes pratiques JavaScript aident également votre application Web React à présenter une expérience utilisateur transparente.
Avant d'entrer dans les techniques d'optimisation, nous devons mieux comprendre le fonctionnement de React.
Au cœur de React se trouve la syntaxe JSX et la capacité de React à construire et comparer. DOM virtuel . Depuis son lancement, React a influencé de nombreuses autres bibliothèques frontales. Les bibliothèques telles que Vue.js reposent également sur l'idée de DOM virtuels.
Voici comment fonctionne React:
Chaque application React commence par un composant racine et se compose de nombreux composants dans une formation arborescente. Les composants de React sont des «fonctions» qui quittent l'interface utilisateur en fonction des données (support et statut) qu'elle reçoit.
Nous pouvons symboliser cela par F
.
UI = F(data)
Les utilisateurs interagissent avec l'interface utilisateur et provoquent une modification des données. Que l'interaction soit en cliquant sur un bouton, en touchant une image, en faisant glisser des éléments d'une liste, des requêtes AJAX qui appellent des API, etc., toutes ces interactions ne modifient que les données. Ils ne modifient jamais directement l'interface utilisateur.
Ici, les données sont tout ce qui définit l'état de l'application Web et pas seulement ce que vous avez stocké dans votre base de données. Même des morceaux des états frontaux (par exemple, quelle fenêtre est sélectionnée pour le moment ou si une case a été cochée pour le moment) font partie de ces données.
Lorsqu'il y a un changement dans ces données, React utilise les fonctions du composant pour re-quitter l'interface utilisateur, mais uniquement virtuellement:
UI1 = F(data1) UI2 = F(data2)
React calcule les différences entre l'interface utilisateur actuelle et la nouvelle interface utilisateur en appliquant un algorithme comparatif sur les deux versions de votre DOM virtuel.
comment concevoir un site Web réactif
Changes = Diff(UI1, UI2)
React applique ensuite uniquement les modifications apportées à l'interface utilisateur réelle dans le navigateur.
Lorsque les données associées au composant changent, React détermine si une mise à jour DOM est réellement nécessaire. Cela permet à React d'éviter des opérations de manipulation DOM coûteuses dans le navigateur, telles que la création de nœuds DOM et l'accès à certains des nœuds existants plus que nécessaire.
Ce calcul de différenciation répété et la sortie de composant peuvent être l'une des principales sources de problèmes de performances de React dans toute application React. La création d'une application React dans laquelle la différenciation des algorithmes ne peut pas être efficacement réconciliée, entraînant ainsi la suppression répétée de l'ensemble de l'application, peut entraîner une expérience frustrante et longue.
Mais qu'optimisons-nous exactement?
Eh bien, pendant le processus initial de laisser derrière, React construit un arbre DOM comme celui-ci:
Étant donné que certaines des données changent, ce que nous voulons que React fasse est de ne supprimer que les composants directement affectés par le changement (et éventuellement d'ignorer le processus de différence pour le reste des composants):
Cependant, ce que React finit par faire est:
comment créer un jeton erc20
Dans l'image ci-dessus, tous les nœuds jaunes sont rendus et différenciés (diff), ce qui entraîne une perte de temps / ressources de calcul. C'est là que nous mettrons nos efforts d'optimisation, principalement. Configurer chaque composant pour ne différencier le rendu (diff) que lorsque cela est nécessaire nous permettra de récupérer ces cycles CPU perdus.
Les développeurs de la bibliothèque React ont pris cela en considération et nous ont fourni un hook pour que nous puissions faire exactement cela: une fonction qui nous permet de dire à React quand il est correct de contourner le rendu d'un composant.
Comme Rob Pike le dit gracieusement comme l'un de ses règles de planification :
À la taille. N'ajustez pas la vitesse avant d'avoir mesuré et ne le faites même pas, à moins qu'une partie du code éclipse le reste.
N'optimisez pas le code qui, selon vous, pourrait ralentir votre application. Au lieu de cela, laissez les outils de mesure des performances de React vous guider tout au long du processus.
React a un outil puissant pour ca. Lors de l'utilisation de react-addons-perf
vous pouvez obtenir un résumé des performances globales de votre application.
L'utilisation est très simple:
Import Perf from 'react-addons-perf' Perf.start(); // use the app Perf.stop(); Perf.printWasted();
Cela imprimera un tableau avec la quantité de composants de temps perdus lors du rendu.
La bibliothèque fournit d'autres fonctions qui vous permettent d'imprimer séparément différents aspects du temps perdu (par exemple, en utilisant les fonctions printInclusive()
ou printExclusive()
), ou même d'imprimer des opérations de manipulation DOM (en utilisant les printOperations()
) .
Si vous êtes une personne visuelle, react-perf-tool
est exactement ce dont vous avez besoin.
react-perf-tool
Il est basé sur la bibliothèque react-addons-perf
. Il vous offre un moyen plus visuel de déboguer les performances de votre application avec React. Il utilise la bibliothèque sous-jacente pour obtenir des mesures, puis les affiche sous forme de graphiques.
Très souvent, c'est un moyen beaucoup plus pratique de remarquer les barres. Vous pouvez facilement l'utiliser en l'ajoutant en tant que composant à votre application.
Par défaut, React s'exécutera, rendra le DOM virtuel et comparera la différence pour chaque composant de l'arborescence pour chaque changement dans leurs accessoires et états. Mais ce n'est évidemment pas rationnel.
fichier principal c++
Au fur et à mesure que votre application se développe, essayer de restituer et de comparer l'intégralité du DOM virtuel à chaque action finira par ralentir.
React fournit un moyen simple pour le développeur d'indiquer si un composant doit être rendu à nouveau. C'est là que le shouldComponentUpdate
entre en jeu.
function shouldComponentUpdate(nextProps, nextState) { return true; }
Lorsque cette fonction renvoie true pour n'importe quel composant, elle permet au processus de différenciation de rendu d'être déclenché.
Cela vous permet de contrôler facilement le processus de différenciation du rendu. Lorsque vous devez empêcher un composant d'être complètement re-rendu, il s'agit simplement d'un résultat falso
de la fonction. À l'intérieur de la fonction, vous pouvez comparer l'ensemble des supports et l'état actuel, ainsi que les éléments suivants pour déterminer si un nouveau rendu est nécessaire:
function shouldComponentUpdate(nextProps, nextState) { return nextProps.id !== this.props.id; }
Pour rendre cette technique d'optimisation un peu plus simple et plus automatisée, React fournit ce que l'on appelle un composant «pur». A React.PureComponent
est exactement comme a React.Component
qui implémente une fonction shouldComponentUpdate()
avec une comparaison vide de soutien et de statut.
A React.PureComponent
est à peu près équivalent à ceci:
class MyComponent extends React.Component { shouldComponentUpdate(nextProps, nextState) { return shallowCompare(this.props, nextProps) && shallowCompare(this.state, nextState); } … }
Comme il n'effectue qu'une comparaison vide, il se peut que vous ne le trouviez utile que lorsque:
llc s corp ou c corp
forceUpdate()
pour mettre à jour votre composant.Et si vous pouviez utiliser React.PureComponent
et avez-vous toujours un moyen efficace de voir quand un support ou un statut complexe a automatiquement changé? C'est là que les structures de données immuables nous facilitent la vie.
L'idée derrière l'utilisation de structures de données immuables est simple. Lorsqu'un objet contenant des données complexes change, au lieu d'apporter les modifications à cet objet, il crée une copie de cet objet avec les modifications. Cela rend la détection des changements dans les données aussi simple que de comparer la référence des deux objets.
Vous pouvez utiliser Object.assign
ou _.extend
(depuis Underscore.js ou Lodash):
const newValue2 = Object.assign({}, oldValue); const newValue2 = _.extend({}, oldValue);
Mieux encore, vous pouvez utiliser une bibliothèque qui fournit des structures de données immuables:
var map1 = Immutable.Map({a:1, b:2, c:3}); var map2 = map1.set('b', 2); assert(map1.equals(map2) === true); var map3 = map1.set('b', 50); assert(map1.equals(map3) === false);
Ici, Immutable.Map
est fourni par la bibliothèque Immutable.js .
Chaque fois qu'une carte est mise à jour avec sa méthode set
, une nouvelle carte est renvoyée uniquement si l'opération set a modifié la valeur sous-jacente. Sinon, la même carte est renvoyée.
Vous pouvez en savoir plus sur l'utilisation de structures de données immuables ici .
Lorsque vous développez une application avec React, vous obtenez des avertissements et des messages d'erreur très utiles. Celles-ci facilitent l'identification des bogues et des problèmes lors du développement. Mais ils coûtent également une partie des performances.
Si vous regardez le code source de React, vous verrez beaucoup de marques if (process.env.NODE_ENV != 'production')
. L'utilisateur n'a pas besoin de ces morceaux de code que React exécute dans votre environnement de développement. Pour les environnements de production, tout ce code inutile peut être supprimé.
Si vous avez poussé votre projet en utilisant create-react-app
, vous pouvez exécuter npm run build
pour produire la version de production sans ce code supplémentaire. Si vous utilisez directement Webpack, vous pouvez exécuter webpack -p
(qui est l'équivalent de webpack --optimize-minimize --define process.env.NODE_ENV=''production''
.
Il est très courant de voir des fonctions liées au contexte du composant dans la fonction rendue. C'est souvent le cas lorsque nous utilisons ces fonctions pour gérer les événements de composants à un stade précoce.
// Creates a new `handleUpload` function during each render() // ...as do inlined arrow functions this.handleUpload(files)} />
Cela provoquera le render()
créer une nouvelle fonction sur chaque rendu. Une meilleure façon de faire de même est:
class App extends React.Component { constructor(props) { super(props); this.handleUpload = this.handleUpload.bind(this); } render() { … … } }
Pour les applications Web React d'une seule page, nous finissons généralement par regrouper tout notre code JavaScript frontal dans un seul fichier réduit. Cela fonctionne très bien pour les applications Web de taille moyenne. Mais à mesure que l'application commence à se développer, la livraison de ce fichier JavaScript attaché au navigateur en tant que tel peut être un processus très long.
Si vous utilisez Webpack pour créer votre application, vous pouvez booster votre code en séparant ses capacités pour séparer également votre code d'application intégré en plusieurs «morceaux» et les livrer au navigateur au moment nécessaire.
Il existe deux types de séparation: la séparation des ressources et la séparation du code à la demande.
console.error(`un bogue connu pour casser npm. veuillez mettre à jour au moins ${r
Avec la séparation des ressources, vous séparez le contenu des ressources en plusieurs fichiers. Par exemple, en utilisant CommonsChunkPlugin, vous pouvez extraire du code commun (comme toutes les bibliothèques externes) dans un fichier de bloc approprié. En utilisant ExtractTextWebpackPlugin, vous pouvez extraire tout le code CSS dans un fichier CSS distinct.
Ce type de séparation vous aidera de deux manières. Il aide le moteur de recherche à stocker les ressources qui changent moins fréquemment. Cela aidera également le chercheur à tirer parti du téléchargement parallèle pour réduire potentiellement le temps de chargement.
Une caractéristique plus notable de Webpack est la séparation du code à la demande. Cela peut limiter le téléchargement initial en réduisant le temps de chargement de l'application. Le navigateur peut, par conséquent, télécharger des morceaux de code à la demande lorsque l'application en a besoin.
Vous pouvez en savoir plus sur la séparation de code Webpack ici .
Le groupe de fichiers JS de l'application React est généralement très volumineux, donc pour accélérer le chargement de la page Web, nous pouvons activer Gzip sur le serveur Web (Apache, Nginx, etc.)
Tous les moteurs de recherche modernes prennent en charge et négocient automatiquement la compression Gzip pour les requêtes HTTP. L'activation de la compression Gzip peut réduire la taille de la réponse transférée de 90%, ce qui peut réduire le temps de téléchargement d'une ressource, réduire l'utilisation des données pour le client et améliorer le temps de rendu de vos pages.
Consultez la documentation de votre serveur Web pour savoir comment activer la compression:
Vous devez utiliser ESLint pour presque tous les projets JavaScript. React n'est pas la différence.
Avec eslint-plugin-react
, vous vous forcerez à vous adapter à de nombreuses règles de programmation de React, ce qui peut profiter à votre code à long terme et éviter de nombreux problèmes et inconvénients courants dus à une mauvaise écriture de code.
Pour tirer le meilleur parti de React, vous devez tirer parti de ses outils et techniques. La performance d'une application web React réside dans la simplicité de ses composants. Le fait de surcharger l'algorithme de différenciation et de rendu peut entraîner des performances médiocres de votre application de manière très frustrante.
Avant de pouvoir optimiser votre application, vous devez comprendre le fonctionnement des composants React et leur rendu dans votre navigateur. Les méthodes de cycle de vie de React vous permettent d'éviter que votre composant ne soit rendu inutilement. Éliminez ces obstacles et vous obtiendrez les performances applicatives que vos utilisateurs méritent.
Bien qu'il existe d'autres moyens d'optimiser une application Web avec React, le raffinement des composants pour les mettre à jour uniquement lorsque cela est nécessaire empêche l'amélioration des performances.
Comment mesurez-vous et optimisez-vous les performances de votre application Web avec React? Partagez-le dans les commentaires ci-dessous.