Wir haben alle das Frustrierungserlebnis, wenn wir lange Ladebildschirmewartezeiten durchstehen müssen, nur um zu erkennen, dass wir an unantwortbaren Seiten stecken bleiben. Sie sehen Ladekreise überall, aber es scheint nichts voran zu gehen. Lasse ich ein klareres Bild für Sie mal:

Das tritt normalerweise auf, weil die Webseite versucht, alle notwendigen Daten sofort zu holen, wenn Sie auf die Seite gelangen. Es könnte sein, dass ein API-Anfrage verarbeitet wird oder mehrere APIs sequentiell Daten holen, was die Ladezeit der Seite verzögert.

Das Ergebnis? Eine schlechte Benutzererfahrung. Sie denken vielleicht: „Wie kann eine solch große Firma die Benutzererfahrung nicht priorisieren? Dies ist enttäuschend.“ Folglich verlassen die Benutzer oft die Webseite, was wichtige Metriken beeinträchtigen und das Einkommen möglicherweise beeinträchtigen kann.

Aber was wenn Sie die Daten für diese langen Seiten bereits vor der Zeit holen könnten, sodass der Benutzer, wenn er auf die Seite gelangt, sofort mit ihr interagieren kann?

Das ist der Ansatz des Prefetchings, und das ist exact, worauf wir in diesem Blogeintrag einsteigen werden. Also, ohne weitere Verzögerung, beginnen wir!

Inhaltsverzeichnis

Vorladen als Lösung

Hier ist die revidierte Fassung mit nur der Grammatik und Rechtschreibung korrigiert:

Für das oben genannte Problem sollten wir die Daten für eine gegebene Seite vor ihrer Ladenzeit auf dem Webportal abrufen, sodass der Benutzer nicht warten muss, bis die Daten beim Seitenaufruf geladen werden. Dies wird als Vorladen bezeichnet.technischer Definition herrscht folgendes:

Es ist eine Methode, die notwendigen Daten vorab abzurufen, sodass das Hauptelement nicht auf die Daten warten muss und somit das Erlebnis verbessert wird.

Dies kann die Benutzererfahrung verbessern und das Vertrauen der Kunden in Ihre Webseite steigern.

Vorladen ist eine einfache und elegante Lösung, die user-centricer ist als ein Standardprozess. Um Vorladen zu implementieren, müssen wir das Verhalten der Benutzer auf der Webseite verstehen. D.h., die meistbesuchten Seiten oder, die Komponenten, die Daten bei kleinen Interaktionen (wie z.B. Mouseover) laden.

Nach der Analyse solcher Szenarien macht es Sinn, Prefetching auf sie anzuwenden. Allerdings sollten wir als Entwickler vorsichtig mit diesem Konzept umgehen. Zu viel Prefetching kann auch Ihre Webseite verlangsamen, da Sie versuchen, viele Daten für zukünftige Szenarien abzurufen, was möglicherweise den Abruf von Daten für die Hauptseite blockieren könnte.

Wie Prefetching die Nutzererfahrung verbessert

Sehen wir uns einige Szenarien an, in denen Prefetching von Vorteil ist:

  1. Daten/seiten früher laden für den am meisten besuchten Link von Ihrer Startseite. Nehmen Sie zum Beispiel Ihren “Kontakt”-Link. Nehmen wir an, dass dies der Link ist, den Benutzer meistens überprüfen und der beim Laden viele Daten enthält. Anstatt die Daten zu laden, wenn die Kontaktseite geladen wird, können Sie einfach die Daten auf der Startseite abrufen, sodass Sie auf der Kontaktseite nicht auf die Daten warten müssen. Mehr über das Prefetching von Seiten hier lesen.

  2. Tabellendaten für spätere Seiten prefetchen.

  3. Daten aus einem Elternkomponenten abrufen und in der Kindkomponente laden.

  4. Vorladen von Daten, die in einem Popover angezeigt werden müssen.

Dies sind einige der Möglichkeiten, um in Ihrer Anwendung Vorladen zu erreichen und wie es die Benutzererfahrung verbessern kann.

In diesem Blogbeitrag werden wir uns diskutieren: Vorladen von Daten, die im Popover angezeigt werden müssen“. Dies ist ein klassisches Beispiel, wo Vorladen von Vorteil sein kann und dem Benutzer eine flüssige Erfahrung bietet.

Problemverständnis

Lassen Sie mich das Problem hier definieren. Stellen Sie sich folgendes Szenarium vor:

  1. Sie haben eine Komponente, die bestimmte Informationen anzeigt.

  2. Es gibt ein Element in dieser Komponente, das, wenn Sie darüber hoverten, ein weiteres Popover/Tooltip anzeigt.

  3. Der Popover lädt Daten, wenn er geladen wird.

Denken Sie nun an die Situation, in der der Benutzer über das Element hovert und auf die Daten wartet, die geladen und im Popover angezeigt werden müssen. Während dieser Wartezeit sieht er den Skelett-Loader.

Das Szenarium wird wie folgt aussehen:

Es ist nur frustrierend, wie lange der Benutzer warten muss, wenn er mit dem Mauszeiger über dem Bild hält:

Um dieses Problem zu lösen, gibt es zwei Lösungen, die Ihnen helfen können, zu beginnen und die Lösung gemäß Ihren Bedürfnissen zu optimieren.

Lösung #1: Daten-Prefetching im Elternkomponenten

Diese Lösung ist inspiriert von einem Blogeintrag von Martin Fowler. Es ermöglicht es Ihnen, die Daten vor der Anzeige des Popups abzurufen, anstatt diese beim Laden der Komponente abzurufen.

Der Popup erscheint, wenn Sie darüber hovern. Wir können die Daten beim Eintritt des Mauszeigers in die Elternkomponente abrufen. Vor dem eigentlichen Komponenten – dem Bild – das gehovert wird, haben wir die Daten für das Popover und geben sie an die Popover-Komponente weiter.

Diese Lösung löst das Ladenseitenbild nicht völlig auf, verringert aber die Wahrscheinlichkeit, das Ladenbild zu sehen, erheblich.

Lösung #2: Daten-Prefetching beim Seiten Laden

Diese Lösung ist inspiriert von x.com, wo sie für die Popover-Komponente die Daten teilweise beim Laden der Hauptseite abrufen und den Rest der Daten beim Mounting der Komponente abrufen.

Wie Sie aus dem obigen Video sehen können, werden die Profildetails des Benutzers im Popover angezeigt. Wenn Sie genau hinschauen, werden die Details, die mit den Followern zu tun haben, später abgerufen.

Diese Technik ist hoch effizient, wenn Sie eine Menge Daten anzeigen müssen, die im Popover zu sehen sind, aber das Abrufen dieser Daten kann teuer sein, wenn das Popover geladen wird oder beim Laden der Hauptseite.

Eine bessere Lösung wäre es, die benötigten Daten teilweise auf der Hauptseite zu laden und den Rest der Daten zu laden, wenn das Komponentenmount erfolgt.

In unserem Beispiel haben wir die Daten für das Popover geladen, wenn der Mauszeiger das übergeordnete Element der Grafik betrat. Stellen Sie sich nun vor, Sie müssen zusätzliche Details abrufen, sobald die Popover-Daten geladen sind. Basierend auf der oben genannten Methode von x.com, können wir zusätzliche Daten beim Laden des Popovers abrufen. Hier ist das Ergebnis davon:

Wir machen folgende Dinge:

  • Wir holen die Hauptdaten ab, die nur notwendig sind, um das Popover zu rendern, wenn die Maus in das übergeordnete Komponente der Grafik geht.

  • Dadurch haben wir genug Zeit, um die Hauptdaten abzurufen.

  • Beim Laden des Popovers holen wir weitere Daten ab, nämlich die Anzahl der Alben. Während der Benutzer Daten wie Name und E-Mail liest, haben wir die nächsten Daten bereit, um sie zu sehen.

Auf diese Weise können wir kleine und kluge Änderungen vornehmen, um das Leeren der Lader auf dem Bildschirm zu minimieren 😊.

Wie implementiere ich das Prefetching mit React?

In diesem Abschnitt werden wir kurz über die Implementierung des oben erwähnten Vorladenbeispiel-Apps berichten.

Projekt Setup

Um mit der Erstellung der Vorlade-App zu beginnen, folgen Sie dem untenstehenden Prozess:

Sie können vitejs (das habe ich verwendet) oder create-react-app verwenden, um Ihre App zu erstellen. Fügen Sie den untenstehenden Befehl in Ihrer Konsole ein:

yarn create vite prefetch-example --template react-ts

Sobald die App erstellt wurde, sollten Sie die folgende Ordnerstruktur haben, wenn Sie die prefetch-example-Datei mit VS Code öffnen.

Jetzt tauchen wir in die Komponenten ein, die wir für diese App bauen werden.

Komponenten

In diesem Beispiel werden wir 3 Komponenten verwenden:

  • PopoverExample

  • UserProfile

  • UserProfileWithFetching

PopoverExample-Komponente

Beginnen wir mit der ersten Komponente, dem PopoverExample. Diese Komponente zeigt ein Bild-Avatar und einige Text links davon an. Es sollte wie folgt aussehen:

Der Zweck dieser Komponente besteht darin, ein Beispiel für reale Lebensszenarien zu sein. Das Bild in dieser Komponente lädt ein Popover-Element, wenn es mit der Maus überfahren wird.

Hier ist der Code für das Komponente:

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>
    );
}

Es passieren hier einige Dinge, lasse mich sie schrittweise erklären:

  • Wir haben eine übergeordnete div mit dem Namen hover-example, die ein Bild und Text enthält.

  • Als nächstes wurde bedingt eine div mit der Klassenbezeichnung floating gerendert. Dies ist die eigentliche Popover-Komponente, die sich öffnet, wenn du mit der Maus über das Bild fährst.

  • Innerhalb des Popovers haben wir bedingt den UserProfile und den Skelett-Lader geladen. Dieser Lader Appears, wenn wir die Daten für das Benutzerprofil abrufen. Mehr dazu später.

  • Wir haben die react-content-loader Bibliothek im MyLoader-Komponenten verwendet. Diese Bibliothek hat auch eine Webseite, die Ihnen hilft, Loader zu erstellen, die Sie hier anschauen können.

UserProfile-Komponente

Nun, da wir unser Popover-Beispiel definiert haben, ist es an der Zeit, die Details der UserProfile-Komponente zu erörtern.

Diese Komponente erscheint innerhalb der Popover-Komponente. Der Zweck dieser Komponente besteht darin, die Daten name, email, phone und website zu laden, die vom JSON placeholder API abgerufen werden.

Um das Beispiel für die Vorladung zu demonstrieren, müssen wir sicherstellen, dass das UserProfile-Komponenten nur als presentational component agiert; d.h., es befindet sich kein explizites Laden von Logik innerhalb von ihm.

Wichtig zu beachten bei dieser Komponente ist, dass das Laden der Daten von der übergeordneten Komponente erfolgt, die das PopoverExample-Komponenten ist. In dieser Komponente beginnen wir das Laden der Daten, wenn der Mauszeiger in diese Komponente gelangt (der mouseenter-Ereignis). Dies ist die Lösung #1, die wir zuvor diskutiert haben.

Dadurch haben Sie genug Zeit, um die Daten bis zum Überfahren des Bildes mit der Maus zu laden. Hier ist der 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>
    );
}

Diese Komponente nutzt die hasAdditionalDetails-Eigenschaft. Der Zweck dieser prop ist, zusätzliche Daten beim Mounting der Komponente zu laden. Sie illustriert die oben erwähnte Lösung #2.

UserProfileWithFetching-Komponente

Diese Komponente ist mit der UserProfile-Komponente sehr ähnlich. Sie enthält nur die Logik zum Laden der Daten, wenn die Komponente geladen wird. Der Zweck dieser Komponente ist es, zu zeigen, wie die allgemeine Lösung ohne die Vorladungstechnik aussehen würde.

Also wird diese Komponente immer die Daten beim Mounting der Komponente laden, was den Skeleton-Loader anzeigt.

Hier ist der 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>
    );
}

Der gesamte Code für diese App kann hier gefunden werden.

Zu viel Vorladen kann auch zu langsamkeit führen

Ein Wort von Rat: Zu viel Vorladen ist nicht gut, weil:

  • Es kann Ihre App verlangsamen.

  • Es kann die Benutzererfahrung verschlechtern, wenn nicht strategisch vorhergeladene Inhalte verwendet werden.

Vorherladen sollte dann angewendet werden, wenn Sie das Verhalten des Benutzers kennen. D.h., Sie können das Nutzerverhalten aufgrund von Metriken vorhersagen und feststellen, ob sie eine Seite oft besuchen. In solchen Fällen ist das Vorherladen eine gute Idee.

Also erinnern Sie sich, Vorherladen Strategien zu verwenden.

Zusammenfassung

Das ist es! Ich hoffe, Sie mögen meinen Blogpost. In diesem Beitrag lernten Sie, dass die Implementierung von Vorherladen die Geschwindigkeit und Reaktionsfähigkeit Ihrer Web-Applikation erheblich verbessern und die Nutzerzufriedenheit steigern kann.

Weitere Informationen finden Sie in den folgenden Artikeln:

Für weitere Inhalte kannst du mich auf Twitter, GitHub, und LinkedIn folgen.