Zum Hauptinhalt springen




Eine reale Fallstudie zur Optimierung der Leistung von React SPA.

Bei der Leistung einer Website geht es nicht nur um die Ladezeit. Die Bereitstellung einer schnellen und reaktionsschnellen Benutzererfahrung ist von entscheidender Bedeutung, insbesondere für die Produktivitäts-Desktop-Anwendungen, die Benutzer täglich verwenden. Das Engineering-Team von Rekrutierungstechnologien ein Refactoring-Projekt durchlaufen, um eine seiner Webanwendungen zu verbessern, AirSHIFT, für eine bessere Leistung bei Benutzereingaben. So haben sie es gemacht.

Langsame Reaktion, geringere Produktivität

AirSHIFT ist eine Desktop-Webanwendung, mit der Ladenbesitzer wie Restaurants und Cafés die Schichtarbeit ihrer Mitarbeiter verwalten können. Die mit React entwickelte Einzelseiten-App bietet umfangreiche Client-Funktionen, einschließlich mehrerer Rastertabellen für Schichtpläne, die nach Tag, Woche, Monat und mehr geordnet sind.

airshift_visual-3001408

Als das Engineering-Team von Recruit Technologies der AirSHIFT-App neue Funktionen hinzufügte, erhielten sie mehr Feedback zu langsamer Leistung. Yosuke Furukawa, technischer Leiter von AirSHIFT, sagte:

In einer Studie zur Nutzerforschung waren wir überrascht, als einer der Ladenbesitzer sagte, er würde seinen Platz verlassen, um nach einem Klick auf einen Knopf Kaffee zu kochen, nur um die Zeit totzuschlagen, die darauf wartet, dass der Schichttisch geladen wird.

Nach Durchführung der Untersuchungen stellte das Engineering-Team fest, dass viele ihrer Benutzer vor 10 Jahren versuchten, massive Schichttabellen auf Computer mit niedrigen Spezifikationen wie einen 1-GHz-Celeron-M-Laptop zu laden.

Endloser Spinner auf Low-End-Geräten.

Die AirSHIFT-Anwendung blockierte den Hauptthread mit teuren Skripten, aber das Engineering-Team erkannte nicht, wie teuer die Skripte waren, da sie auf Rich-Spec-Computern mit schnellen Wi-Fi-Verbindungen entwickelt und getestet wurden.

Haupt-Thread-Breakdown-7210124

Beim Laden der Schichttabelle wurden etwa 80% der Ladezeit durch Ausführen von Skripten verbraucht.

Nach der Profilerstellung der Leistung in Chrome DevTools mit aktivierter CPU- und Netzwerkdrosselung wurde klar, dass die Leistung optimiert werden muss. AirSHIFT hat eine Arbeitsgruppe gebildet, um dieses Problem anzugehen. Hier sind 5 Dinge, auf die sie sich konzentriert haben, um ihre App reaktionsschneller auf Benutzereingaben zu machen.

1. Virtualisieren Sie große Tabellen

Das Anzeigen der Schichttabelle erforderte mehrere kostspielige Schritte: Erstellen des virtuellen DOM und Rendern auf dem Bildschirm im Verhältnis zur Anzahl der Mitarbeiter und Zeitfenster. Wenn ein Restaurant beispielsweise 50 arbeitende Mitglieder hat und Sie den monatlichen Schichtplan überprüfen möchten, ist dies eine Tabelle mit 50 (Mitgliedern) multipliziert mit 30 (Tagen), was dazu führt, dass 1.500 Zellkomponenten gerendert werden. Dies ist eine sehr teure Operation, insbesondere für Geräte mit niedrigen Spezifikationen. In Wirklichkeit war es schlimmer. Bei der Untersuchung stellten sie fest, dass es Geschäfte gab, in denen 200 Mitarbeiter verwaltet wurden und die rund 6.000 Zellkomponenten in einer einzigen monatlichen Tabelle benötigten.

Um die Kosten für diesen Vorgang zu senken, hat AirSHIFT die Schichttabelle virtualisiert. Die Anwendung stellt jetzt nur die Komponenten im Ansichtsfenster und die Komponenten außerhalb des Bildschirms bereit.

virtualize_before-9209523

Vorher: Rendern aller Zellen der Verschiebungstabelle.

virtualize_after-8560709

Nachher: Rendern Sie einfach die Zellen im Ansichtsfenster.

In diesem Fall wird AirSHIFT verwendet virtualisiert reagieren da es Anforderungen gab, komplexe zweidimensionale Rastertabellen zu ermöglichen. Sie suchen auch nach Möglichkeiten, die Implementierung so zu konvertieren, dass sie in Zukunft das Lichtreaktionsfenster verwendet.

Ergebnisse

Die Tabellenvirtualisierung allein reduzierte die Skriptzeit um 6 Sekunden (in einer Macbook Pro 4x langsamer + schnellen 3G-beschleunigten Umgebung). Dies war die effektivste Leistungsverbesserung im Refactoring-Projekt.

virtualize_results_before-4813935

Vorher: ca. 10 Sekunden Skript nach Benutzereingabe.

virtualize_results_after-6955380

Nachher: 4 Sekunden Skript nach Benutzereingabe.

2. Audit mit API User Timing

Das AirSHIFT-Team hat dann die Skripte überarbeitet, die mit Benutzereingaben ausgeführt werden. das Flammentabelle
von Chrome DevTools
Mit dieser Option können Sie analysieren, was im Hauptthread tatsächlich passiert. Das AirSHIFT-Team fand es jedoch einfacher, die Anwendungsaktivität basierend auf dem React-Lebenszyklus zu analysieren.

React 16 bietet seine Leistungsverfolgung über die
Benutzerzeit-API, die Sie von der sehen können
Times Abschnitt
von Chrome DevTools. AirSHIFT verwendete den Abschnitt "Zeiten", um unnötige Logik zu finden, die in React Lifecycle-Ereignissen ausgeführt wird.

user_timing-6925370

Reagieren Sie auf Benutzerzeitereignisse.

Ergebnisse

Das AirSHIFT-Team stellte fest, dass a
Reaktionsbaum-Versöhnung
es geschah kurz vor jeder Schifffahrtsstraße. Dies bedeutete, dass React die Schichttabelle vor den Navigationen unnötig aktualisierte. Eine unnötige Aktualisierung des Redux-Status verursachte dieses Problem. Durch das Reparieren wurden ca. 750 ms Skriptzeit eingespart. AirSHIFT hat auch andere Mikrooptimierungen vorgenommen, die schließlich zu einer Verkürzung der Programmierzeit um insgesamt 1 Sekunde führten.

3. Lazy Loading-Komponenten und kostspielige Logikübertragung an Web-Worker

AirSHIFT verfügt über eine integrierte Chat-Anwendung. Viele Ladenbesitzer kommunizieren mit ihren Mitarbeitern per Chat, während sie sich die Schichttabelle ansehen. Dies bedeutet, dass ein Benutzer möglicherweise eine Nachricht eingibt, während die Tabelle geladen wird. Wenn der Hauptthread mit Skripten beschäftigt ist, die die Tabelle rendern, kann die Benutzereingabe ärgerlich sein.

Um diese Erfahrung zu verbessern, verwendet AirSHIFT jetzt React.lazy und Suspense, um Platzhalter für Tabelleninhalte anzuzeigen, während die eigentlichen Komponenten langsam geladen werden.

Das AirSHIFT-Team hat auch einen Teil der teuren Geschäftslogik in träge geladenen Komponenten auf migriert
Web-Worker. Dies löste das Problem mit Benutzereingaben, indem der Haupt-Thread freigegeben wurde, sodass er sich darauf konzentrieren konnte, auf Benutzereingaben zu reagieren.

In der Regel sind Entwickler bei der Verwendung von Workern mit Komplexität konfrontiert, diesmal jedoch Comlink tat das schwere Heben für sie. Nachfolgend finden Sie den Pseudocode, wie AirSHIFT bei einer der teuersten Operationen gearbeitet hat, die sie jemals hatten: Berechnung der Gesamtarbeitskosten.

Verwenden Sie in App.js React.lazy und Suspense, um Sicherungsinhalte beim Laden anzuzeigen


importieren Reagieren, { faul, Suspense } desde 'react'


const Hello = faul(() => importieren('./Cost'))

const Loading = () => (
<div>Some fallback content to show während Wird geladen</div>
)


Export Standard Funktion App({ userInfo }) {
Rückkehr (
<div>
<Suspense fallback={<Loading />}>
<Cost />
</Suspense>
</div>
)
}

Verwenden Sie in der Kostenkomponente comlink, um die Berechnungslogik auszuführen


importieren Reagieren desde 'react';
importieren { proxy } desde 'comlink';


const WorkerlizedCostCalc = proxy(new Arbeiter('./WorkerlizedCostCalc.js'));
Export Standard Funktion Cost({ userInfo }) {
const instance = erwarten new WorkerlizedCostCalc();
const cost = erwarten instance.calc(userInfo);
Rückkehr <p>{cost}</p>;
}

Implementieren Sie die Berechnungslogik, die auf dem Worker ausgeführt wird, und legen Sie sie mit comlink offen


importieren { expose } desde 'comlink'
importieren { someExpensiveCalculation } desde './CostCalc.js'


expose({
calc(userInfo) {
Rückkehr someExpensiveCalculation(userInfo);
}
}, selbst);

Ergebnisse

Trotz der begrenzten Menge an Logik, die sie als Test arbeiteten, wechselte AirSHIFT etwa 100 ms seines JavaScript vom Hauptthread zum Arbeitsthread (simuliert mit 4x CPU-Gas).

Arbeiter-7404546

AirSHIFT prüft derzeit, ob andere Komponenten verzögert geladen und mehr Logik an Web-Worker ausgelagert werden können, um den Ruck weiter zu reduzieren.

4. Erstellen Sie ein Leistungsbudget

Bei all diesen Optimierungen war es wichtig sicherzustellen, dass die Anwendung im Laufe der Zeit weiterhin funktioniert. AirSHIFT verwendet jetzt Paket Größe Überschreiten Sie nicht die aktuelle JavaScript- und CSS-Dateigröße. Zusätzlich zum Festlegen dieser Grundbudgets wurde ein Dashboard erstellt, in dem verschiedene Perzentile der Ladezeit der Schichttabelle angezeigt werden, um zu überprüfen, ob die App auch unter nicht idealen Bedingungen funktioniert.

  • Jetzt wird die Skriptabschlusszeit für jedes Redux-Ereignis gemessen
  • Leistungsdaten werden in gesammelt Elasticsearch
  • Die Leistung des 10., 25., 50. und 75. Perzentils jedes Ereignisses wird mit angezeigt Kibana

AirSHIFT überwacht jetzt das Ladeereignis der Schichttabelle, um sicherzustellen, dass es für Benutzer mit 75. Perzentil in 3 Sekunden abgeschlossen ist. Dies ist derzeit ein nicht angewendetes Budget, sie erwägen jedoch automatische Benachrichtigungen über Elasticsearch, wenn sie Ihr Budget überschreiten.

kibana-9058952

Das Kibana-Dashboard zeigt die täglichen Leistungsdaten nach Perzentilen an.

Ergebnisse

In der obigen Grafik sehen Sie, dass AirSHIFT jetzt hauptsächlich das 3-Sekunden-Budget für Benutzer des 75. Perzentils erreicht und die Verschiebungstabelle für Benutzer des 25. Perzentils in einer Sekunde lädt. Durch die Erfassung von RUM-Leistungsdaten von verschiedenen Bedingungen und Geräten kann AirSHIFT dies jetzt tun Überprüfen Sie, ob eine neue Feature-Version die Leistung der Anwendung wirklich beeinträchtigt oder nicht.

5. Performance-Hackathons

Obwohl all diese Bemühungen zur Leistungsoptimierung wichtig und wirkungsvoll waren, ist es nicht immer einfach, Engineering- und Geschäftsteams dazu zu bringen, nicht funktionale Entwicklungen zu priorisieren. Ein Teil der Herausforderung besteht darin, dass einige dieser Leistungsoptimierungen nicht geplant werden können. Sie erfordern Experimente und eine Versuch-und-Irrtum-Denkweise.

AirSHIFT führt jetzt interne eintägige Leistungs-Hackathons durch, damit sich Ingenieure nur auf leistungsbezogene Arbeiten konzentrieren können. Bei diesen Hackathons beseitigen sie alle Einschränkungen und respektieren die Kreativität der Ingenieure. Daher ist jede Implementierung, die zur Geschwindigkeit beiträgt, eine Überlegung wert. Um den Hackathon zu beschleunigen, teilt AirSHIFT die Gruppe in kleine Teams auf und jedes Team konkurriert darum, wer den größten bekommen kann Leuchtturm Verbesserung der Leistungsbewertung. Teams werden sehr wettbewerbsfähig! 🔥

Hackathon-2457180

Ergebnisse

Der Hackathon-Ansatz funktioniert gut für sie.

  • Leistungsengpässe können leicht erkannt werden, indem mehrere Ansätze während des Hackathons getestet und jeweils mit Lighthouse gemessen werden.
  • Nach dem Hackathon ist es ziemlich einfach, das Team davon zu überzeugen, welche Optimierung es für die Produktionsfreigabe priorisieren sollte.
  • Es ist auch ein wirksamer Weg, um die Bedeutung der Geschwindigkeit zu verteidigen. Alle Teilnehmer können den Zusammenhang zwischen der Art und Weise, wie Sie codieren, und der Umsetzung in die Leistung verstehen.

Ein netter Nebeneffekt war, dass sich viele andere Entwicklungsteams innerhalb von Recruit für diesen praktischen Ansatz interessierten und das AirSHIFT-Team jetzt Hackathons mit mehreren Geschwindigkeiten innerhalb des Unternehmens ermöglicht.

Zusammenfassung

Es war definitiv nicht die einfachste Reise für AirSHIFT, an diesen Optimierungen zu arbeiten, aber es hat sich auf jeden Fall gelohnt. Jetzt lädt AirSHIFT die Schichttabelle in 1,5 Sekunden auf den Median, was eine 6-fache Verbesserung gegenüber der Leistung vor dem Projekt darstellt.


Nachdem die Leistungsoptimierungen veröffentlicht wurden, sagte ein Benutzer:

Vielen Dank, dass Sie das Laden des Schichttisches beschleunigt haben. Die Organisation der Schichtarbeit ist jetzt viel effizienter.