Früher oder später wird jeder Frontend-Entwickler auf das Problem stoßen, dass die schöne Anwendung, die er erstellt hat, aufgrund unerwartet großer Datenmengen Leistungsprobleme hat.
Die Symptome können leicht ausfallen und lediglich zu einer Verlangsamung der Anwendung führen, sie können aber auch so schwerwiegend sein, dass die Anwendung einfriert und geschlossen werden muss.
Die häufigste Lösung für dieses Problem ist die Aufteilung in Seiten. Hol die Daten in Stücken vom Server und zeige immer nur eine Seite auf einmal an. Diese Lösung ist völlig in Ordnung und wurde bereits zu Tode gebloggt.
Die zweite Lösung, über die ebenfalls schon viel geschrieben wurde, ist das unendliche Scrollen. Dabei handelt es sich im Grunde um eine hübsche Version der Aufteilung in Seiten, bei der die Daten geladen werden, wenn man das Ende der Seite erreicht. Heute wollen wir uns ein paar andere Möglichkeiten ansehen, wie die Leistung einer App beim Umgang mit großen Datenmengen verbessert werden kann.
Bevor wir uns mit den Vorschlägen befassen, müssen wir zunächst unser Problem definieren. Stell dir vor, wir haben einen Server, der eine riesige Menge an Daten im JSON-Format zurückgibt. Wir sprechen hier von Hunderttausenden von Datensätzen. Der Server unterstützt keine Aufteilung in Seiten der Ergebnisse und du musst die Daten im Browser anzeigen.
Was ist unser eigentliches Problem mit großen Datenmengen im Frontend? Ist die Speichernutzung ein Engpass?
Browser haben heutzutage Zugang zu riesigen Speichermengen, stürzen unsere Anwendungen also wirklich wegen großer Datenmengen ab? Nicht wirklich.
Es sind nicht die Daten, die das größte Problem darstellen, sondern die beiden teuersten Teile des Prozesses sind das Übertragen der Daten an den Browser und das Rendern von Elementen in den DOM.
Wenn erst ein paar hundert Megabyte geholt werden müssen, bevor die Anwendung initialisiert wird, muss der Benutzer eine Weile warten, bis er etwas tun kann. Auch wenn erst alles gerendert werden muss, führt jedes Element zu einer kleinen Leistungseinbuße. Diese Einbußen sind nicht sichtbar, wenn es nur eine kleine Anzahl von Datensätzen gibt, aber mit zunehmender Anzahl summieren sich diese kleinen Einbußen ziemlich schnell.
Das Cachen von Daten ist ein Prozess, bei dem mehrere Kopien von Daten oder Dateien an einem temporären Speicherort - oder im Cache - gespeichert werden, damit schneller auf sie zugegriffen werden kann.
Durch Caching können nachfolgende Zugriffe auf dieselben Daten beschleunigen und, wenn du es richtig anstellst, die Interaktionsgeschwindigkeit erheblich verbessern.
Stell dir ein Szenario vor, in dem ein Benutzer beim ersten Mal 10 Sekunden warten muss, wenn er die Benutzeroberfläche aufruft. Wenn er dann versehentlich nach dem Laden auf Aktualisieren klickt, muss er weitere 10 Sekunden warten. Damit wird er nicht zufrieden sein.
Wenn die Aufrufe aber beim ersten Mal zwischengespeichert werden, kann der Benutzer die Anwendung neu laden und beim zweiten Mal wird sie viel schneller geladen. Wenn sich deine Daten nicht pro Sekunde ändern, gibt es wirklich keinen Grund, all diese Daten bei jeder Aktualisierung oder beim Wechsel zu einer anderen Seite neu zu laden.
Die gute Nachricht ist, dass Browser heutzutage bereits API-Aufrufe zwischenspeichern, wenn sie ähnlich sind. Dies setzt aber voraus, dass die Header auf dem Server korrekt eingerichtet sind. Wenn der Server die Cache-Kontrolle korrekt gesetzt sind, sollte alles in Ordnung sein. Ist dies nicht der Fall, können die Daten immer noch in der Anwendung zwischengespeichert werden, anschließend wird die Benutzeroberfläche initialisiert und dann erfolgt ein Aufruf, um die aktuellen Daten im Hintergrund abzurufen.
Beim Lazy Loading oder asynchronen Laden wird mit dem Laden von Ressourcen gewartet, bis diese benötigt werden. Es ist das IT-Äquivalent zu Restaurants, welche die Vorspeise servieren, während sie noch mit der Zubereitung des Hauptgerichts beschäftigt sind. Wenn du mit mehreren Aufrufen arbeitest und einige dieser Aufrufe nicht erforderlich sind, damit der Benutzer zunächst arbeiten kann, solltest du den Aufruf dieser Endpunkte verzögern. Konzentriere dich darauf, dem Nutzer zuerst Interaktivität zu geben, und lade den Rest im Hintergrund, wenn klar ist, dass es benötigt wird.
Dies ist ein üblicher Trick, der bei Bildern angewandt wird: Bilder, die weiter unten auf der Seite liegen und für den Benutzer nicht sichtbar sind, werden erst geladen, wenn der Benutzer beginnt, zu ihnen zu scrollen.
Wenn das Laden von Daten, die nicht sofort benötigt werden, verzögert werden kann, trägt dies erheblich zur Verbesserung der Leistung bei.
Nur weil die API dir alle Daten geschickt hat, heißt das nicht, dass alle Daten für den Nutzer relevant sind. Wenn die API dir Daten liefert, die in 7 Kategorien unterteilt sind, und dein Nutzer sich nur für drei davon interessiert, ist die Anzeige der anderen vier eine Verschwendung von Zeit und Ressourcen.
Filtere diese Ergebnisse heraus und schreiben sie gar nicht erst in den DOM. Das macht die Anwendung reaktionsschneller. Achte jedoch darauf, dass der Benutzer eine Möglichkeit hat, auf diese versteckten Datensätze zuzugreifen. Nichts ist ärgerlicher für den Benutzer, als wenn er weiß, dass Daten vorhanden sind, er aber keine Möglichkeit hat, darauf zuzugreifen.
Ja, ich weiß, ich habe gesagt, dass die API keine Aufteilung in Seiten beherrscht, aber das gilt nur serverseitig. Wenn die Daten schnell im Browser sind, kannst du die Aufteilung in Seiten trotzdem umsetzen.
Aufteilen in Seiten im Frontend ist eine Sache, die ziemlich einfach einzurichten ist. Du musst nur die Anzahl der „Seiten“ berechnen, auf denen deine Daten angezeigt werden sollen, und für jede „Seiten“ eine Teilmenge der Daten anzeigen.
Ehrlich gesagt, ist es ganz einfach. Hier ist ein Blick auf den Code, den du benötigst, um das Ganze zum Laufen zu bringen, und ich habe mir kaum Mühe gegeben.
Dieser Code gibt dir etwas, das wie folgt aussieht:
Unendliches Scrollen ist eine etwas flüssigere Art der Aufteilung in Seiten. Dabei werden zunächst einige wenige Ergebnisse angezeigt, und wenn der Benutzer bis zum Ende der Liste oder Tabelle blättert, werden weitere Datensätze hinzugefügt. Im Gegensatz zur reinen Aufteilung in Seiten muss der Benutzer nicht explizit eine Seitenzahl auswählen, zu der er wechseln möchte, und das ist benutzerfreundlicher.
Ein Nachteil ist, dass der Benutzer Dinge wie Links oder Kontaktangaben am unteren Ende der Seite erst sehen kann, wenn alle Datensätze angezeigt wurden. Ein weiterer Nachteil ist, dass Elemente, die einmal in das DOM geschrieben wurden, für die gesamte Lebensdauer der Seite dort verbleiben, und wenn die Seite groß genug ist, wird die Leistung beeinträchtigt.
Microsoft Excel hat über eine Million Zeilen und über 16 Tausend Spalten, aber es zeigt nicht alle gleichzeitig auf dem Bildschirm an.
Die Datenvirtualisierung im Frontend macht es Excel gleich und ermöglicht es dir, nur die Daten darzustellen, die gerade auf dem Bildschirm sichtbar sind, anstatt den gesamten Datensatz darzustellen.
Dies ist eine großartige Technik, um Benutzern den Zugriff auf große Datenmengen auf effiziente und intuitive Weise zu ermöglichen. Sie vereint die besten Eigenschaften der Aufteilung in Seiten und des unendlichen Scrollens, da sie sehr einfach zu bedienen ist und nur eine begrenzte Anzahl von Elementen auf dem Bildschirm zeigt. Ein weiterer Unterschied zu Pagination und unendlichem Scrolling besteht darin, dass bei richtiger Anwendung nicht immer eine ganze Seite an Datensätzen in den DOM geschrieben wird. Wenn du also drei Datensätze weit scrollst, werden nur drei neue Datensätze zum DOM hinzugefügt, während drei andere entfernt werden.
Es gut auf dem Frontend zu implementieren ist ein kleiner Alptraum, aber zum Glück gibt es Plugins dafür, wenn man im React-Ökosystem ist, kann man Plugins wie react-virtualized und react-window, wenn man Vue benutzt, kann man vue-virtual-scroller oder vue-virtual-scroll-grid. Die anderen Frameworks haben alle Plugins, die das Gleiche tun, also werde ich sie hier nicht alle auflisten, aber es reicht zu sagen, dass es einfach ist es nachzuschlagen und zu implementieren.
Man muss sich vor Augen halten, dass das Netzwerk und der DOM zwei der größten Probleme sind, die man lösen muss, um mit großen Datenmengen zu arbeiten. Die Größe der Daten selbst kann das Problem sein, aber mit der ständig wachsenden Leistung moderner PCs ist das weniger relevant als andere Faktoren.