Nous avons tous connu la frustration de devoir attendre sous de longues images de chargement, seulement pour découvrir que nous sommes bloqués sur des pages non-réponsives. Vous voyez des animations de chargement partout, mais rien ne semble avancer. Permettez-moi de vous peindre un tableau plus clair :
Cela se produit généralement parce que le site Web s’efforce de récupérer toutes les données nécessaires dès que vous atteignez la page. Il peut s’agir d’une demande API en cours de traitement, ou de multiples API qui récupèrent les données séquentiellement, causant des retards dans le chargement de la page.
Le résultat ? Une mauvaise expérience utilisateur. Vous pouvez penser : « Comment une entreprise aussi importante peut-elle ne pas prioritiser l’expérience utilisateur ? C’est décevant. » Par conséquent, les utilisateurs quittent souvent le site, affectant les indicateurs clés et potentiellement impactant le revenu.
Mais imaginez-vous si vous pouviez récupérer les données pour ces pages lourdes avant-même, de sorte que lorsque l’utilisateur atteint la page, il peut interagir avec elle instantanément ?
C’est là que le concept de pré-chargement entre en jeu, et c’est exactement ce que nous allons aborder dans ce billet de blog. Donc, sans plus attendre, voyons commencer !
Table des matières
-
Solution n°1 : Préchargement des données dans le composant parent
-
Solution n°2 : Précharger les données au chargement de la page
Préchargement en tant que solution
Voici la version révisée avec uniquement la grammaire et l’orthographe corrigées :
Pour le problème ci-dessus, ce que nous voulons, c’est charger les données d’une page donnée avant qu’elle ne soit chargée sur le site web, de sorte que l’utilisateur n’ait pas à les charger au chargement de la page. C’est ce que l’on appelle le préchargement. Du point de vue technique, sa définition est la suivante :
C’est une méthode pour charger à l’avance les données nécessaires de sorte que le composant principal n’ait pas à attendre les données, améliorant ainsi l’expérience.
Cela peut améliorer l’expérience utilisateur, renforçant la confiance du client dans votre site web.
Le préchargement est une solution simple et élégante qui est plus axée sur l’utilisateur que le processus standard. Pour mettre en œuvre le préchargement, nous devons comprendre le comportement de l’utilisateur sur le site web. C’est-à-dire, les pages les plus visitées ou les composants qui chargent des données lors de petites interactions (comme le survol).
Après l’analyse de tels scénarios, il est logique d’appliquer le préchargement à eux. Cependant, en tant que développeurs, nous devrions être conscients de l’utilisation de ce concept. Un trop grand préchargement peut également ralentir votre site web, car vous essayez de récupérer beaucoup de données pour des scénarios futurs, ce qui pourrait bloquer le chargement des données de la page principale.
Comment le préchargement améliore l’expérience utilisateur
Faisons un tour d’horizon de quelques scénarios où le préchargement est bénéfique :
-
Chargement de données/page plus tôt pour le lien le plus visité de votre page d’accueil. Par exemple, imaginez que vous avez un lien “contactez-nous”. Supposons que ce soit le lien que les utilisateurs consultent le plus souvent et qu’il contienne beaucoup de données au chargement. Au lieu de charger les données lorsque la page de contact est chargée, vous pouvez simplement récupérer les données sur la page d’accueil afin qu’il ne faille pas attendre sur la page Contactez-nous pour les données. Vous pouvez en apprendre plus sur le préchargement de pages ici.
-
Préchargement des données de table pour les pages suivantes.
-
Récupération de données depuis un composant parent et chargement de ces données dans le composant enfant.
-
Préchargement de données destinées à être affichées dans un tooltip.
Ceci sont quelques-unes des manières d’obtenir un préchargement dans votre application et de la manière dont cela améliore l’expérience utilisateur.
Dans ce billet de blog, nous discuterons du dernier scénario : “préchargement de données destinées à être affichées dans le tooltip”. C’est un exemple classique où le préchargement peut être bénéfique et fournir une expérience plus fluide pour l’utilisateur.
Comprendre le problème
Permettez-moi de définir le problème ici. Imaginez le scénario suivant :
-
Vous avez un composant qui affiche des informations spécifiques.
-
Il y a un élément dans ce composant qui affiche un autre tooltip/popover lorsque vous passez la souris dessus.
-
Le tooltip charge les données lors de son chargement.
Maintenant, imaginez que l’utilisateur passe la souris sur l’élément et doit attendre que les données soient chargées et affichées dans le tooltip. Pendant cette attente, il voit le chargeur d’icônes.
Le scénario se présentera comme suit :
Il est tellement frustrant comment longtemps l’utilisateur doit attendre chaque fois qu’il survole l’image :
Pour résoudre ce problème, il existe deux solutions qui peuvent vous aider à démarrer et à optimiser la solution selon vos besoins.
Solution n°1 : Préchargement des données dans le composant parent
Cette solution est inspirée de le post de blog de Martin Fowler. Elle permet de récupérer les données avant l’apparition de la popup, plutôt que de les récupérer à la charge du composant.
La popup apparaît lorsque vous survolez dessus. Nous pouvons récupérer les données lorsque la souris entre dans le composant parent. Avant que le composant réel, l’image, ne soit survolé, nous aurons les données pour la popover et les passerons au composant popover.
Cette solution n’enlève pas complètement l’état de chargement, mais elle permet de réduire significativement les chances de voir l’état de chargement.
Solution n°2 : Préchargement des données à la page chargement
Cette solution est inspirée par x.com où, pour le composant popover, ils récupèrent les données partiellement à la charge de la page principale et récupèrent le reste des données lorsque le composant est monté.
Comme vous pouvez le voir dans la vidéo ci-dessus, les détails du profil de l’utilisateur sont affichés dans la popover. Si vous observez attentivement, les détails liés aux abonnés sont récupérés plus tard.
Cette technique est très efficace lorsque vous devez afficher beaucoup de données dans un tooltip, mais à un coût élevé lors de l’initialisation du tooltip ou du chargement de la page principale.
Une solution plus avancée serait de charger partiellement les données requises sur la page principale et de charger le reste des données lors du mount du composant.
Dans notre exemple, nous avons récupéré les données pour le tooltip lorsque le curseur a entré dans l’élément parent de l’image. Maintenant, imaginez que vous devez récupérer des détails additionnels une fois que les données du tooltip sont chargées. Ainsi, en s’inspirant de la méthode de x.com précitée, nous pouvons récupérer des données supplémentaires au chargement du tooltip. Voici les résultats de cela :
Dans ce cas, nous effectuons les actions suivantes :
-
Nous récupérons les données principales nécessaires pour afficher le tooltip lorsque le curseur entre dans l’élément parent de l’image.
-
Cela nous donne suffisamment de temps pour récupérer les données principales.
-
Lors du chargement du tooltip, nous récupérons une autre donnée, qui est le nombre d’albums. pendant que l’utilisateur lit des données telles que le nom et l’email, nous aurons les données suivantes prêtes à être vues.
Ainsi, nous pouvons apporter de petites optimisations intelligentes pour minimiser les tirs d’attente des chargeurs à l’écran 😊.
Comment implémenter la pré-récupération avec React.
Dans cette section, nous passerons brièvement sur la manière de mettre en œuvre l’exemple d’applications de préchargement ci-dessus.
Configuration du projet
Pour commencer à créer l’application de préchargement, suivez le processus ci-dessous :
Vous pouvez utiliser vitejs (c’est ce que j’ai utilisé) ou create-react-app pour créer votre application. collez la commande ci-dessous dans votre terminal :
yarn create vite prefetch-example --template react-ts
Une fois que l’application a été créée, vous devriez avoir la structure de dossier suivante lorsque vous ouvrez le dossier prefetch-example avec VS Code.
Maintenant, nous plongerons dans les composants que nous allons construire pour cette application.
Composants
Dans cet exemple, nous allons utiliser 3 composants :
-
PopoverExample
-
UserProfile
-
UserProfileWithFetching
PopoverExample
Composant
Commençons par le premier composant, qui est le PopoverExample
. Ce composant affiche un avatar d’image et du texte à droite de celui-ci. Il devrait ressembler à ceci :
Le but de ce composant est de servir d’exemple similaire aux scénarios réels de vie. L’image dans ce composant charge un composant de popover lorsqu’elle est survolée.
Voici le code du composant :
import { useState } from "react";
import { useFloating, useHover, useInteractions } from "@floating-ui/react";
import ContentLoader from "react-content-loader";
import UserProfile from "./UserProfile";
import UserProfileWithFetching from "./UserProfileWithFetching";
export const MyLoader = () => (
<ContentLoader
speed={2}
width={340}
height={84}
viewBox="0 0 340 84"
backgroundColor="#d1d1d1"
foregroundColor="#fafafa"
>
<rect x="0" y="0" rx="3" ry="3" width="67" height="11" />
<rect x="76" y="0" rx="3" ry="3" width="140" height="11" />
<rect x="127" y="48" rx="3" ry="3" width="53" height="11" />
<rect x="187" y="48" rx="3" ry="3" width="72" height="11" />
<rect x="18" y="48" rx="3" ry="3" width="100" height="11" />
<rect x="0" y="71" rx="3" ry="3" width="37" height="11" />
<rect x="18" y="23" rx="3" ry="3" width="140" height="11" />
<rect x="166" y="23" rx="3" ry="3" width="173" height="11" />
</ContentLoader>
);
export default function PopoverExample() {
const [isOpen, setIsOpen] = useState(false);
const [isLoading, setIsLoading] = useState(false);
const [data, setData] = useState({});
const { refs, floatingStyles, context } = useFloating({
open: isOpen,
onOpenChange: setIsOpen,
placement: "top",
});
const hover = useHover(context);
const { getReferenceProps, getFloatingProps } = useInteractions([hover]);
const handleMouseEnter = () => {
if (Object.keys(data).length === 0) {
setIsLoading(true);
fetch("https://jsonplaceholder.typicode.com/users/1")
.then((resp) => resp.json())
.then((data) => {
setData(data);
setIsLoading(false);
});
}
};
return (
<div
id="hover-example"
style={{
display: "flex",
flexDirection: "row",
alignItems: "center",
textAlign: "left",
}}
onMouseEnter={handleMouseEnter}
>
<span
style={{
padding: "1rem",
}}
>
<img
ref={refs.setReference}
{...getReferenceProps()}
style={{
borderRadius: "50%",
}}
src="https://cdn.jsdelivr.net/gh/alohe/avatars/png/vibrent_5.png"
/>
</span>
<p>
Lorem Ipsum is simply dummy text of the printing and typesetting
industry. Lorem Ipsum has been the industry's standard dummy text ever
since the 1500s, when an unknown printer took a galley of type and
scrambled it to make a type specimen book. It has survived not only five
centuries, but also the leap into electronic typesetting, remaining
essentially unchanged. It was popularised in the 1960s with the release
of Letraset sheets containing Lorem Ipsum passages, and more recently
with desktop publishing software like Aldus PageMaker including versions
of Lorem Ipsum.
</p>
{isOpen && (
<div
className="floating"
ref={refs.setFloating}
style={{
...floatingStyles,
backgroundColor: "white",
color: "black",
padding: "1rem",
fontSize: "1rem",
}}
{...getFloatingProps()}
>
{isLoading ? (
<MyLoader />
) : (
<UserProfile hasAdditionalDetails {...data} />
)}
{/* <UserProfileWithFetching /> */}
</div>
)}
</div>
);
}
Plusieurs choses se passent ici, laissez-moi vous les expliquer étape par étape :
-
Nous avons un
div
parent nomméhover-example
qui contient une image et du texte. -
Ensuite, nous avons rendu conditionnellement un
div
avec le nom de classefloating
. C’est le composant de popover réel qui s’ouvre lorsque vous survolez l’image.- Nous avons utilisé la bibliothèque
floating-ui
et son exemple de survol de base pour réaliser l’effet de survol pour le popover.
- Nous avons utilisé la bibliothèque
-
Dans le popover, nous avons chargé conditionnellement le
UserProfile
et le chargeur d’illustration. Ce chargeur apparaît lorsque nous récupérons les données pour le profil de l’utilisateur. Plus sur cela plus tard. -
Nous avons utilisé la bibliothèque react-content-loader dans le composant
MyLoader
. Cette bibliothèque possède également un site Web qui vous aide à créer des chargeurs, vous pouvez le voir ici.
Composant UserProfile
Maintenant que nous avons défini notre exemple de Popover
, il est temps de nous plonger dans les détails du composant UserProfile
.
Ce composant apparaît à l’intérieur du composant popover. L’objectif de ce composant est de charger les détails name
email
phone
website
qui sont récupérés de l’API de placeholder JSON.
Pour démontrer l’exemple d’anticipation, nous devons nous assurer que le composant UserProfile
ne s’agit que d’un composant présentiel ; c’est-à-dire qu’il n’y a pas de logique d’appel explicite à l’intérieur de celui-ci.
La clé à noter à propos de ce composant est que la récupération des données se produit depuis le composant parent, soit le composant PopoverExample
. Dans ce composant, nous commençons à récupérer les données lorsque la souris entre dans ce composant (l’événement mouseenter
). C’est la solution n°1 que nous avons discutée précédemment.
Cela vous donne suffisamment de temps pour récupérer les données jusqu’à ce que l’utilisateur survole l’image. Voici le code :
import { useEffect, useState } from "react";
import ContentLoader from "react-content-loader";
const MyLoader = () => (
<ContentLoader
speed={2}
viewBox="0 0 476 124"
backgroundColor="#d1d1d1"
foregroundColor="#fafafa"
>
<rect x="4" y="43" rx="0" ry="0" width="98" height="30" />
</ContentLoader>
);
export default function UserProfile(props: Record<string, string | boolean>) {
const { name, email, phone, website, hasAdditionalDetails } = props;
const [isLoading, setIsLoading] = useState(false);
const [additionalData, setAdditionalData] = useState(0);
useEffect(() => {
if (hasAdditionalDetails) {
setIsLoading(true);
fetch("https://jsonplaceholder.typicode.com/albums")
.then((resp) => resp.json())
.then((data: Array<unknown>) => {
const albumCount = data.reduce((acc, curr) => {
if (curr.userId === 1) acc += 1;
return acc;
}, 0);
setAdditionalData(albumCount);
})
.finally(() => {
setIsLoading(false);
});
}
}, [hasAdditionalDetails]);
return (
<div id="user-profile">
<div id="user-name">name: {name}</div>
<div id="user-email">email: {email}</div>
<div id="user-phone">phone: {phone}</div>
<div id="user-website">website: {website}</div>
{hasAdditionalDetails && (
<>
{isLoading ? (
<MyLoader />
) : (
<div id="user-albums">Album Count: {additionalData}</div>
)}
</>
)}
</div>
);
}
Ce composant utilise la propriété hasAdditionalDetails
. L’objectif de cette propriété prop
est de charger des données supplémentaires lors du chargement du composant. Elle illustre la solution n°2 mentionnée ci-dessus.
Composant UserProfileWithFetching
Ce composant est assez similaire à celui du composant UserProfile
. Il contient juste la logique de récupération des données lors du chargement du composant. L’objectif de ce composant est de montrer ce que la solution générale sans la technique d’anticipation serait comme.
Donc, ce composant chargera toujours les données lorsque le composant sera monté, ce qui affichera le chargeur d’ squelette.
Voici le code :
import { useEffect, useState } from "react";
import { MyLoader } from "./PopoverExample";
export default function UserProfileWithFetching() {
const [isLoading, setIsLoading] = useState(false);
const [data, setData] = useState<Record<string, string>>({});
useEffect(() => {
setIsLoading(true);
fetch("https://jsonplaceholder.typicode.com/users/1")
.then((resp) => resp.json())
.then((data) => {
setData(data);
setIsLoading(false);
});
}, []);
if (isLoading) return <MyLoader />;
return (
<div id="user-profile">
<div id="user-name">name: {data.name}</div>
<div id="user-email">email: {data.email}</div>
<div id="user-phone">phone: {data.phone}</div>
<div id="user-website">website: {data.website}</div>
</div>
);
}
Le code entier pour cette application peut être trouvé ici.
Trop d’anticipation peut aussi provoquer la lenteur
Un mot d’advice, trop d’anticipation n’est pas bon car :
-
Cela pourrait ralentir votre application.
-
Il peut dégrader l’expérience utilisateur si le préchargement n’est pas appliqué stratégiquement.
Le préchargement doit être utilisé lorsque vous connaissez le comportement de l’utilisateur. C’est-à-dire que vous pouvez prédire le déplacement de l’utilisateur par des métriques et savoir si il visite souvent une page. Dans ce cas, le préchargement est une bonne idée.
Donc, souvenez-vous de toujours appliquer le préchargement stratégiquement.
Sommaire
C’est tout pour aujourd’hui ! J’espère que vous aimerez mon article de blog. Dans cet article de blog, vous avez appris que l’implémentation de préchargement peut améliorer significativement la vitesse et la réactivité de votre application Web, améliorant ainsi la satisfaction des utilisateurs.
Pour un complément de lecture, veuillez vous référer aux articles ci-dessous :
Pour plus de contenu, vous pouvez me suivre sur Twitter, GitHub, et LinkedIn.
Source:
https://www.freecodecamp.org/news/boost-web-performance-with-prefetching/