Fermer

janvier 28, 2022

Obtenez de meilleures performances lors du développement de React


Cet article couvre React Suspense et React Lazy, qui peuvent être utilisés pour diviser le code, récupérer des données et définir l'ordre dans lequel les composants sont rendus, ce qui vous donne le contrôle total de votre projet.

L'un des problèmes auxquels les développeurs sont confrontés lorsqu'ils il s'agit de performances Web, c'est le rendu des éléments inutilisés dans le DOM. Cela augmente le temps de chargement du site Web car le site doit télécharger tous les éléments nécessaires avant de montrer quoi que ce soit à l'utilisateur. Plus il a besoin d'éléments, plus il faut de temps pour le charger, ce qui est le problème majeur auquel de nombreux sites Web sont confrontés aujourd'hui, de nombreux utilisateurs abandonnant même lorsqu'ils essaient de charger la page.

Les performances d'un site Web déterminent beaucoup ce que l'utilisateur va faire. l'expérience, l'augmentation des visites sur le site Web et l'obtention de bons commentaires. Dans cet article, nous expliquerons comment obtenir de meilleures performances avec React.

Nous aborderons ce qui suit dans cet article :

Au fur et à mesure, nous créerons une application simple pour nous aider à tout comprendre en pratique .

Prérequis

Pour suivre cet article, vous devez avoir :

  • Une compréhension de base de React
  • Node installé
  • Un éditeur de texte

Qu'est-ce que React JS ?

React est une bibliothèque JavaScript permettant de créer des interfaces utilisateur rapides et interactives ; il a été développé sur Facebook en 2011 et est actuellement la bibliothèque JavaScript la plus populaire pour la création d'interfaces utilisateur.

React utilise un développement basé sur des composants : les fonctionnalités sont décomposées en composants réutilisables ultérieurement dans d'autres parties de l'application. Un projet React typique doit avoir au moins un composant, qui est le composant racine, généralement appelé App.js dans la plupart des projets React, mais vous pouvez également modifier le nom en fonction de vos besoins.

Commençons avec la création d'un projet React. Saisissez la commande suivante dans votre terminal.

npx create-react-app performance-checker

Maintenant que nous avons créé notre projet React, installons les packages que nous allons utiliser. Voici la liste des packages que nous utiliserons et leurs fonctions :

  • React Router : React Router en tant que package est composé de composants de navigation utilisés pour naviguer sur l'ensemble du site Web. Il est utilisé pour attribuer des pages dans un projet React.
  • Styled-components : Il est utilisé pour écrire du CSS en JS sous forme de composants réutilisables dans toutes les parties du projet. Les composants stylisés utilisent la syntaxe du format SASS pour créer un composant d'un style CSS.

Saisissez la commande suivante pour installer les packages.

npm i react-router-dom styled-components

Qu'est-ce que le fractionnement de code ?

Lors de la création d'une application React, l'ensemble du projet est compilé dans un fichier build.js utilisé pour rendre le site Web. Dans ce cas, le contenu qui n'est pas nécessaire est téléchargé, ce qui rend le fichier groupé volumineux avec un long temps de téléchargement ; cela augmente le temps de chargement du site Web.

Le fractionnement de code divise le fichier groupé en morceaux en fonction des besoins de l'utilisateur ou de ce que l'utilisateur souhaite voir. Cette idée entraîne une diminution du temps de chargement du site Web puisque les utilisateurs devront télécharger un fichier groupé plus petit, offrant aux utilisateurs une meilleure expérience. pour rendre les sites Web plus rapides, non pas pour le chargement initial mais pour l'interaction de l'utilisateur et d'autres chargements. En gros, cela implique de mesurer les performances et d'enregistrer des mesures de la rapidité de chargement d'un site Web.

Il est fortement influencé par la psychologie et la perception des utilisateurs concernant le chargement. Quelle que soit la lenteur avec laquelle un site Web se charge, si l'utilisateur sent que le site Web se charge rapidement, alors il se charge rapidement. Une partie essentielle de l'amélioration des performances Web comprend l'amélioration des performances perçues, qui consiste à donner l'impression que le site Web se charge rapidement. Réagissez, il regroupe les pages entières dans un fichier bundle.js, après quoi le DOM commence à rendre le contenu du site Web. Parfois, les choses peuvent devenir plus fatigantes lorsque le projet est énorme et qu'il doit télécharger tous les fichiers du bundle en même temps. Pour cette raison, le fractionnement de code a été introduit dans React en tant que mécanisme permettant de diviser les fichiers groupés en morceaux en fonction de la page requise par l'utilisateur. cela réduit la taille des fichiers à télécharger avant le rendu, ce qui améliore le temps de chargement.

Qu'est-ce que React Suspense ?

React Suspense peut être considéré comme un moyen de suspendre le rendu des composants pendant la récupération des données. Cela aide à communiquer que les données nécessaires au rendu ne sont pas prêtes, rendant un composant de secours en place pendant le chargement des données.

Lorsque le réseau est lent ou que la page ne se charge pas, cela donne au développeur la possibilité d'afficher un espace réservé qui évite de perturber la vue de l'utilisateur.

React Suspense est utilisé de trois manières différentes :

  • Au niveau du routage
  • Lors de la récupération des données
  • Au niveau du composant

React Suspense au niveau du routage

Lorsque configuration d'un itinéraire pour un projet React, React Suspense peut être utilisé avec React Lazy pour diviser la taille du bundle par page. Nous utiliserons React Router pour configurer la route afin de rendre cela possible, et nous utiliserons React Lazy et React Suspense pour diviser le code.

Avant de pouvoir commencer le routage, nous devons mettre certaines choses en place ; tout d'abord, nous devons créer un dossier dans le dossier src avec le nom pagesqui contiendra tous les composants de la page.

mkdir pages.

Dans le dossier, créez un fichier nommé home.jsx et collez le code passe-partout suivant à l'intérieur.

touch home.jsx

importer Réagir de 'réagir'

const Accueil = () =>  retour (
        <>
          Bonjour
        </>
    )
}
exporter par défaut Accueil ;

Ensuite, créez un fichier posts.jsx pour la page de publication.

touchez post.jsx

À l'avenir, créez un dossier components dans le dossier src ; c'est là que nos composants seront stockés. De la structure du projet, nous aurons six composants avec les noms suivants : HomeHeaderNavPostListsSinglePost User et UserList.

Maintenant, collez le code suivant dans HomeHeader.jsx :

import React fromfrom ]'réagir'
import Style from 'styled-components'

import { FaUsers } actfrom 'reactfrom  icônes/fa';
import { BsFilePost } from 'react-icons/bs';

const Accueil  = ({titre, publication}) => {
    retour[1965] 19659088]<En-tête stylisé>
            {
                poster  ?
                <BsFilePost className="icon" />[1965:9104][1965:91]<FaUsers className="icône" />
            }
            {titre[37]4590[19]4590[19]4590[19] 
        </StyledHeader>
    )
}
export default HomeHeader
const StyledHeader = Styled.div`
    largeur : 100 % ;
    rembourrage : 2rem 1,5rem ;
    taille de police : 2,5 rem ;
    poids de la police : 700 ;
    arrière-plan : #170448 ;
    couleur : #fff ;
    affichage : flexible ;
    align-items : center ;
    justifier-contenu : centrer ;
    .icon {
        taille de police : 4 rem ;
        couleur : #fff ;
        marge-droite : 1rem ;
    }
`

Le code ci-dessus contient chaque titre de page que nous utiliserons plus tard. Nous importons simplement styled-components pour le style, react-icons pour certaines icônes et obtenons le titre et les données de publication en tant qu'accessoires.

Ensuite, collez le code suivant dans le Fichier Nav.jsx :

import React from 'react'
import Styled from[196590] composants'
import { NavLink } from 'react-router-dom'
const Nav = ( ( ( ( (  ]) => {
    return (
        <StyledNav>
            <NavLink exact[19365Class90]exact[19365Class90="actif" à="/">
             </NavLink>
            <NavLink exact activeClassName=[19659047]"actif" vers="/messages">[19659141</]Messages[1965] NavLink>
        </StyledNav>
    )
}
exporter Nav par défaut[1945]
const StyledNav = Styled.nav`
    largeur : 100 % ;
    affichage : grille ;
    grille-modèle-colonnes : répéter (2, 1fr) ;
    une {
        largeur : 100 % ;
        affichage : flexible ;
        align-items : center ;
        justifier-contenu : centrer ;
        rembourrage : 1rem ;
        arrière-plan : #fff ;
        couleur : #170448 ;
        &.actif, &:hover {
            arrière-plan : #170448 ;
            couleur : #fff ;
        }
    }
`

Ce composant sert de base pour naviguer l'utilisateur d'une page à l'autre en utilisant NavLink de react-router-dom. Nous avons défini le activeClassName pour donner à la page actuelle un style différent et nous nous arrêterons ici pour l'instant tout en continuant l'interface utilisateur restante tout en récupérant les données.

Regardons la manière standard de routage dans React par rapport à l'utilisation de React Le suspense. Voici la méthode standard de routage dans React :

import {
  NavigateurRouter as Router,
  Commutateur,
  Route
} de "réagir-routeur-dom" ;

pages
import Accueil de './pages/Accueil'
import Messages de "./pages/Messages";[19659043]fonction Application() {
  retour (
    <Routeur>
      <Nav />
      <Commutateur>
          <Route chemin exact="/"> <[1945904]<

/> </Itinéraire> <Route chemin exact="/messages"> <[196452]<[196452] ]/> </Itinéraire> </Interrupteur> </Routeur> ); }

Alors, que se passe-t-il dans le bloc de code ci-dessus ? En utilisant react-router-domnous devons importer BrowserRouterSwitch et Route.

  • BrowserRouterBrowserRouterBrowserRouter ] est utilisé pour envelopper les routes ; sans cela, l'itinéraire ne fonctionnera pas.
  • Switch permet de naviguer entre les itinéraires ; tout ce qu'il contient est affecté à une route, tandis que les composants extérieurs s'affichent dans toutes les pages.
  • Route spécifie la page à afficher lorsqu'un lien est cliqué.

Ensuite, voici le routage à l'aide de React Suspense :

importer Réagir, {paresseux, Suspense} de "réagir "réagir 19659058]importer {
  NavigateurRouter as Router,
  Commutateur,
  Route
} from "react-router-dom";
import Nav from "./components/Nav";[19659058]import { UserPlaceholder } from "./components/User";

const Accueil = lazy = paresseux(() => import("./pages/Messages")[19])6904 

fonction Application() {
  retour (
    <Routeur>
      <Nav />
      <Switch>
        <Suspense fallback={<UserPlaceholder />} 0
          <Route chemin exact="/"> <[1945904]<

/> </Itinéraire> <Route chemin exact="/messages"> <[196452]<[196452] ]/> </Parcours> </Suspense> </Interrupteur> </Routeur> ) ; } exporter par défaut Application ;

Quelle est la différence entre ces deux approches ? En regardant la deuxième approche, vous verrez que nous importons les pages avec React Lazy. Cela nous permet d'utiliser React Suspense avec un repli lorsque la page n'est pas chargée ; Cela nous permettra de télécharger les données en fonction de ce que l'utilisateur demande.

React Suspense While Fetching Data

Lorsque vous essayez de récupérer des données dans React, il existe trois approches :

  • Fetch on Rendu (sans suspense) : Cette approche est le moyen standard de récupérer des données dans une application React où vous récupérez les données lorsque le composant est rendu à l'écran en utilisant componentDidMount ou UseEffect. Cette approche introduit une faille connue sous le nom de cascadedans laquelle elle doit attendre que d'autres composants soient rendus avant de commencer la récupération, ce qui peut perturber le déroulement du programme, en particulier si les données récupérées sont importantes pour la vue. . () (19659047] () ;
    }

    UseEffect ( ([19659047]) => {
    récupérer des articles();
    }, [9659047]][47] ];

    • Récupérer puis rendre (sans suspense) : Il s'agit d'un moyen de récupérer toutes les données avant le rendu. Cela résout le problème de la cascade, mais l'utilisateur doit attendre que toutes les données soient récupérées avant d'interagir avec l'application. L'expérience utilisateur peut être frustrante, surtout si l'application récupère beaucoup de données, ce qui peut ralentir l'application. .tous([
      getInfo(),
      getName())))))) ]).alors(([info,nom]) =>[1965] {
      retour {info, nom};
      })
      }

      En utilisant Promise, nous pouvons récupérer toutes les données, puis les utiliser une par une plus tard en cas de besoin.

      • Render as You Fetch (using Suspense) : C'est l'approche dont nous allons parler aujourd'hui, où nous effectuerons le rendu lors de la récupération. Il commence le rendu et la demande réseau démarre immédiatement. Voyons comment le configurer. Créez un fichier Api.js dans le dossier src et collez le code suivant à l'intérieur.
      const fetchUsers = ()[19659045]=> {
          console.log('Récupération des données des utilisateurs...')
          return fetch('https://jsonplaceholder .typicode.com/users?_Limit=25')
          .then(réponse => réponse.json[19659047]())
          .puis(json => json)
      } 5const[4196]5const[4196]5 récupérer les messages = () => {
          console.log('Récupération des données des utilisateurs...')
          return fetch('https://jsonplaceholder .typicode.com/posts?_limit=25')
          .then(réponse => réponse.json[19659047]())
          .puis(json => json)
      }
      

      Ensuite, nous allons créer une fonction pour les données que nous voulons récupérer. La fonction utilise généralement l'API Fetch pour obtenir les données dont nous avons besoin.

      Ensuite, nous pouvons créer notre wrap Promise à l'aide de cette fonction et mettre à jour le code avec celle-ci. Ajoutez le code ci-dessous en haut du code précédent. ]let statut = 'en attente'

      let résultat

      laisser suspendre = promesse.puis(
      res => {
      statut = 'succès'
      résultat = res
      },
      erreur => {
      état= 'erreur'
      résultat = erreur
      }
      )
      retour {
      lire() {
      si ([19459004=904]état [1945=904] 'en attente') {
      lancer bretelle
      } else if (état === 'erreur') {
      lancer[4] résultat
      } else if (état === 'success') {
      retour[4]45900
      }
      }
      }
      }

      La fonction wrapPromise prend une promesse en paramètre ; c'est la fonction que nous avons créée pour récupérer nos données. Ensuite, nous créons une variable de suspension où nous vérifions si la réponse renvoie un succès ou une erreur. Nous renvoyons une sortie basée sur le statut.

      Enfin, nous créons une fonction fetchData pour rassembler toutes les récupérations à l'aide du code ci-dessous.

      export const fetchData[19659045] =   ( )   {  {  UsersPromise  =   Fetchusherers  () 
           Const  postPromise = fetchPosts()
          return {
              utilisateurs : wrapPromise(usersPromise),
              posts : wrapPromise(postPromise)
          }
      }
      

      C'est la fonction que nous exporterons pour utiliser lorsque nous essaierons d'obtenir nos données.

      Créons nos composants restants pour rendre l'application fonctionnelle. Dans le dossier PostLists.jscollez ce code :

      import React from 'react'
      import Styled from  'styled-components'
      import { fetchData } from '../Api'
      import {Poste unique} from './SinglePost'
      const ressource = fetchData()
      6PostLists[19]65904 = () => {
          const messages = ressource.messages.[4465]lire. ()
          retour (
              <StyledList>
                  {
                      posts.carte(({ titre, id, corps }[1965] 19659045]=> (
                          <SinglePost 
                              clé={id}
                              titre={titre}
                              contenu={corps}
                          />
                      ))
                  }
              </StyledList>
          )
      }
      exporter listes de messages par défaut[19459]
      const StyledList = Styled.div`
          largeur : 100 % ;
          affichage : grille ;
          grille-modèle-colonnes : répéter (2, 1fr) ;
          écart de grille : 0,7 rem ;
      `
      

      En regardant le code ci-dessus, vous pouvez voir que nous utilisons le fetchData que nous venons de créer, qui est affecté à une variable de ressource ; ceci est ensuite utilisé pour obtenir les données de la publication en utilisant const posts = resource.posts.read().

      Nous pouvons maintenant cartographier les données de la publication et transmettre les données au composant SinglePost. Pour créer le composant SinglePost, ouvrez votre fichier SinglePost.js et collez ce code.

      import React from 'react'
      import Stylisé, {images clés} from 'styled-components'
      
      export const SinglePost 0 { titre, contenu }) => {
          retour (
              <[1945] 19659047]>
                  <h3>{titre}</h3[19]65904]5 p>{contenu}</p>
              0</[19088] StyledPost>
          )
      }
      export const PostPlaceholder = () =0{19659095]=0{19659095]=0 
          retour (
              <StyledPost className="placeholder"01[34565]91[294657]>

      div className="title-placeholder"></div>[1965] div className="content-placeholder"></div[47]>[90] 19659132]<div className="content-placeholder"></[07]4590 ]> <div className="content-placeholder">90</[19] div> </StyledPost> ) } const Animation 90=[1965s]90=[1965s] ]` à partir de { opacité : .4 ; } à { opacité : 1 ; } ` const StyledPost = Styled.div` largeur : 100 % ; rembourrage : 1rem ; arrière-plan : #fef7f7 ; &.placeholder { largeur : 100 % ; rembourrage : 1rem ; arrière-plan : #d8cccc ; animation : ${Animation} 0,6 s d'entrée et de sortie infinie ; } h3 { poids de la police : 700 ; taille de police : 1,5 rem ; couleur : #000 ; } .title-placeholder { largeur : 50 % ; hauteur : 1,5 rem ; arrière-plan : #fff ; marge inférieure : 1rem ; } p { taille de police : 1rem ; poids de la police : 400 ; couleur : #000 ; hauteur de ligne : 1,5 ; marge supérieure : 0,8 rem ; } .content-placeholder { largeur : 80 % ; hauteur : 1rem ; arrière-plan : #fff ; marge inférieure : 0,5 rem ; } `

      Cette structure de composants est simple ; nous avons deux sous-composants à l'intérieur. L'un est responsable du rendu de chaque message tandis que l'autre sert de solution de secours. Si les données sont toujours en cours de récupération, elles seront rendues.

      Collez le code suivant dans le fichier UserList.js pour afficher la liste. d'utilisateurs.

      import React from 'react';
      import {User}[19641265]from  ]'./User';
      import { fetchData } from '../Api'
      const ressource  = fetchData()
      const UserList = () => {[1965t9050]5 utilisateurs = ressource.utilisateurs.lire()
          retour (
              <[1965>13]{
                      utilisateurs.carte(({ e-mail, nom, identifiant,[1945]}) => (
                          <Clé 
                              utilisateur={identifiant}
                              e-mail={e-mail}
                              nom={nom}
                              imgUrl={`https://via.placeholder.com/32/${nom d'utilisateur} `}
                          />
                      ))
                  }
              </>
          )
      }
      exporter par défaut Liste d'utilisateurs
      

      Nous utilisons le même modèle que pour le composant de liste de publications : utilisez la fonction fetchData pour obtenir les données et envoyer les données au composant User en mappant les données.

      Pour le composant utilisateur, collez le code suivant à l'intérieur : {images clés} from 'styled-components'

      export const User = ({{

      {

      {

      , nom, e-mail }) => {
      retour (
      <
      <
      ]>
      <div className="user-details">
      90<[19]img90<
      src={imgUrl} alt= {nom} />
      <div nom_classe="nom-utilisateur[4]">{nom}</div>
      0</
      0 >
      <div className="user-email">[47]{19004][47]{9004 ]e-mail}</div>
      </StyledUser>
      )[1965[90] 19659058]export const UserPlaceholder = () => (
      <StyledUser className="placeholder">
      <
      <[19459088]<[19459088] ="détails-utilisateur">
      <div className= " "" espace réservé"></div>
      <div className=[447] ]espace réservé au nom d'utilisateur" />
      </div>
      <div className[1965] ]="espace réservé pour l'adresse e-mail de l'utilisateur" />

      </StyledUser>
      )
      const Animer = images clés`
      à partir de {
      opacité : .4 ;
      }
      à {
      opacité : 1 ;
      }
      `

      const StyledUser = Styled.div`
      largeur : 100 % ;
      rembourrage : 1,5 rem 1 rem ;
      marge : .8rem 0 ;
      affichage : flexible ;
      align-items : center ;
      justifier-contenu : espace entre ;
      arrière-plan : #fff8f8 ;
      rayon de bordure : 8 px ;
      curseur : pointeur ;
      transition : toutes les 0,3 s d'entrée et de sortie ;
      @media (largeur maximale : 768px) {
      flex-direction : colonne ;
      align-items : flex-start ;
      justifier-contenu : centrer ;
      }
      &.placeholder {
      animation :
      ${Animation} 0,6 s d'entrée et de sortie infinie ;
      }
      &: survolez {
      arrière-plan : #f5ecec ;
      }
      .user-details {
      affichage : flexible ;
      align-items : center ;
      image {
      largeur : 32px ;
      hauteur : 32px ;
      rayon de bordure : 50 % ;
      }
      .img-placeholder {
      largeur : 32px ;
      hauteur : 32px ;
      rayon de bordure : 50 % ;
      arrière-plan : #efdfdf ;
      }
      .Nom d'utilisateur {
      taille de police : 1rem ;
      poids de la police : 500 ;
      couleur : #000 ;
      marge-gauche : 1 rem ;
      &.placeholder {
      largeur : 100 pixels ;
      hauteur : 1,2 rem ;
      arrière-plan : #efdfdf ;
      }
      }
      }
      .user-email {
      taille de police : 1rem ;
      poids de la police : 400 ;
      couleur : #000 ;
      @media (largeur maximale : 768px) {
      marge supérieure : 0,8 rem ;
      }
      &.placeholder {
      largeur : 80 pixels ;
      hauteur : 1,2 rem ;
      arrière-plan : #efdfdf ;
      }
      }
      `

      Réagissez Suspense au niveau du composant

      Enfin, mettons à jour les pages. Open the Home.js file and paste this code:

      import React, { Suspense, SuspenseList } from 'react'
      import HomeHeader from '../components/HomeHeader'
      import UserList from '../components/UsersList'
      import { UserPlaceholder } from '../components/User'
      const Home = () => {
          return (
              <>
                  <SuspenseList revealOrder="forwards">
                      <Suspense fallback="loading....">
                          <HomeHeader title='Users' />
                      </Suspense>
                      <Suspense 
                          fallback={
                              <>
                                  <UserPlaceholder />
                                  <UserPlaceholder />
                                  <UserPlaceholder />
                              </>
                          }>
                          <UserList />
                      </Suspense>
                  </SuspenseList>
              </>
          )
      }
      export default Home;
      

      Looking at the code above, you can see that we are using SuspenseList and Suspense to render the files. SuspenseList is used to set the priority to which the data is fetched and rendered. In contrast, Suspense wraps the component and controls the state depending on if the data is still fetching or has completed the fetch.

      Let’s work on the posting page. Paste the following code into the Posts.js file:

      import React, { Suspense, SuspenseList } from 'react'
      import Styled from 'styled-components'
      import HomeHeader from '../components/HomeHeader'
      import PostLists from '../components/PostLists'
      import { PostPlaceholder } from '../components/SinglePost'
      const Posts = () => {
          return (
              <>
                  <SuspenseList revealOrder="forwards">
                      <HomeHeader title="Posts" post />
                      <Suspense 
                          fallback={
                              <Grid>
                                  <PostPlaceholder />
                                  <PostPlaceholder />
                                  <PostPlaceholder />
                                  <PostPlaceholder />
                                  <PostPlaceholder />
                                  <PostPlaceholder />
                              </Grid>
                          }
                      >
                          <PostLists />
                      </Suspense>
                  </SuspenseList>
              </>
          )
      }
      export default Posts
      const Grid = Styled.div`
          width: 100%;
          display: grid;
          grid-template-columns: repeat(2, 1fr);
          grid-gap: .7rem;
      `
      

      Testing

      Run the following command in the terminal to start up the project.

      npm start
      

      Project running in browser shows users list

      Let’s check how effective it is, starting from the routing level. I was able to check the size before using React Suspense and after using it.

      Here’s the size before using React Suspense—the bundle size was 8.1 kb.

      Bundle file size without React Suspense - 8.1 kb

      And after adding React Suspense, the bundle size decreased to 202 b.

      Bundle file size with React Suspense - 202 b

      Lastly, after using Suspend on both component and data fetching levels, I was able to get this:

      lazy loading screen - first we see home and posts tabs at the top, then a posts header, then card indicators fading on to show loading

      That improves the user’s visual perspective about the project, which may help them wait even longer even if the site is slow.

      Conclusion

      In this post, we covered what React, web performance, and code-splitting are. Also, we covered React Suspense and how to properly use it in routing level, component level and data-fetching level.




Source link