webentwicklung-frage-antwort-db.com.de

Angular JS Scaling & Performance

Mit einer Angular App, die wir für eine Bank entwickeln, kämpfen wir gegen Performance-Probleme.

Leider ist es ein Vertragsbruch, Codeausschnitte anzuzeigen. Unabhängig davon kann ich einige der Hauptprobleme beschreiben und hoffe, dass Best Practices empfohlen werden können.

Anwendungsstruktur:

  • Im Wesentlichen eine riesige Seite mit mehreren Formularen.
  • Jedes Formular ist ein eigenes Teil, mit verschachtelten Controllern und Partials, die ungefähr 3 Ebenen tief sind.
  • Dieselben Formen werden über eine Sammlung von JSON-Objekten wiederholt.
  • Jedes Formular ist an das Objekt/Modell gebunden, über das es wiederholt wird.
  • Wir sollen 1-200 Formulare auf der Seite unterstützen.

Wenn Sie einen Blick auf die Timeline werfen. Wir verbringen viel Zeit mit der Methode jQuery parse html, der Methode jQuery recalculate stye, dem GC Event (Garbage Collection). Ich stelle mir vor, diese zu minimieren, sollte die Dinge etwas beschleunigen. Sie sind alle Teil des Angular Lebenszyklus, aber es gibt möglicherweise bessere Möglichkeiten, sie zu vermeiden. Hier sind einige Screenshots des Profilers:

Recalculate StyleGC Event

Letztendlich ist die App träge, da die Anzahl der wiederholten Formulare über 5 liegt. Jedes Formular ist relativ unabhängig von den anderen. Wir haben versucht, keine gemeinsamen Eigenschaften zwischen den Formularen zu überwachen.

42
trevorewen

Sie müssen benutzerdefinierte Direktiven erstellen, um die Leistungsprobleme mit angle einzudämmen. Im Gegensatz zu ember angular) sind alle Schnickschnack aktiviert und es liegt an Ihnen, dies zu entschärfen. Hier sind ein paar Anweisungen, die ich erstellt habe Nicht alle Daten in Ihrer App müssen bidirektional datengebunden sein, daher können Sie wertvolle CPU-Leistung sparen, indem Sie bei Bedarf auf Überwachungsausdrücke auf der Seite verzichten. Alle diese Anweisungen binden Daten einmal und lassen sie in Ruhe.

https://Gist.github.com/btm1/6802599

https://Gist.github.com/btm1/6802312

https://Gist.github.com/btm1/674615

In einer der obigen Antworten wird davon gesprochen, dass ng-repeat enorme Leistungseinbußen aufweist. Daher gebe ich Ihnen "set-repeat" als einmalige Datenbindungs-Wiederholungsanweisung :)

21
btm1

Es ist schwierig, eine Lösung ohne weitere Informationen zu Ihrem Problem zu finden, aber ich habe vor kurzem festgestellt (und gelöst), dass ein Leistungsproblem dem ähnelt, was Sie gesehen haben, und in keinem Zusammenhang mit dem $ digest-Zyklus stand.

Die meisten Diskussionen über Angulars Performance (einschließlich des exzellenten Postings von Misko ) beziehen sich auf die Performance von Dirty Checks und den $ digest-Zyklus. Dies ist jedoch nicht das einzige Leistungsproblem, das bei AngularJS auftreten kann. Der erste Schritt sollte darin bestehen, festzustellen, ob der Digest-Zyklus Ihr Problem ist oder nicht. Hierfür können Sie Batarang verwenden oder sich einfach Ihre App ansehen und sehen, wann sie genau träge ist. Wenn der Digest-Zyklus langsam ist, ist im Wesentlichen jede Interaktion mit der Benutzeroberfläche langsam.

OTOH, Sie können eine App mit einem schnellen Digest-Zyklus haben, der nur langsam ist, wenn Sie die anzuzeigenden Komponentensätze laden, Ansichten wechseln oder auf andere Weise ändern. Dies kann sich in der Profilerstellung als viel Zeitaufwand für das Parsen von HTML und Garbage manifestieren sammeln. In meinem Fall wurde dies durch eine Vorberechnung der anzuzeigenden HTML-Vorlage gelöst, anstatt sich auf ng-repeat, ng-switch und ng-if überall zu verlassen.

Ich habe ein ng-repeat = "Widget in Widgets" verwendet, das einen ng-Schalter für den Widget-Typ enthielt, um einen beliebigen Satz von Widgets anzuzeigen (benutzerdefinierte, in sich geschlossene Anweisungen). Ersetzen Sie dies durch Code, um die Vorlage angular) für die spezifischen Widgets zu generieren, und beschleunigen Sie den Routenwechsel von ~ 10s auf praktisch sofort.

Im oben genannten Google Groups-Thread finden Sie weitere Informationen zur Lösung meines Problems. Wenn Sie spezielle Vorschläge wünschen, können Sie weitere Informationen zu Ihrer Anwendung bereitstellen.

8
jssebastian

Um die Leistung in der Produktion zu verbessern, lesen Sie unten den sehr schönen Einzeiler:

AngularJS-Dokumentation zitieren:

Standardmäßig fügt AngularJS Informationen zur Bindung und zu Bereichen an DOM-Knoten an und fügt datengebundenen Elementen CSS-Klassen hinzu:

Infolge von ngBind-, ngBindHtml- oder {{...}} -Interpolationen werden Bindungsdaten und die CSS-Klasse ng-binding an das entsprechende Element angehängt.

Wenn der Compiler einen neuen Bereich erstellt hat, werden der Bereich und entweder die CSS-Klasse ng-scope oder ng-isolated-scope an das entsprechende Element angehängt. Auf diese Bereichsreferenzen kann dann über element.scope () und element.isolateScope () zugegriffen werden.

Tools wie Protractor und Batarang benötigen diese Informationen, um ausgeführt zu werden. Sie können diese jedoch in der Produktion deaktivieren, um die Leistung erheblich zu steigern.

myApp.config(['$compileProvider', function ($compileProvider) {
  $compileProvider.debugInfoEnabled(false);
}]);

Sie können mehr Details lesen hier

4
Abbasi

Im Allgemeinen arbeitet AngularJS schlecht, wenn mehr als 2000 Datenbindungen aktiv sind, d. H. 2000 Elemente im Gültigkeitsbereich, die in jedem $ digest-Zyklus einer Dirty-Prüfung unterzogen werden. Ng-Repeat hat aus diesem Grund einen großen Einfluss auf die Leistung. Jedes wiederholte Element erstellt mindestens zwei Bindungen, wobei zusätzliche Daten oder Anweisungen, die im Element verwendet werden, nicht berücksichtigt werden.

Einer der Entwickler hinter AngularJS gibt eine hervorragende Beschreibung der Details der Dirty-Checks und ihrer Leistung in dieser SO answer:

https://stackoverflow.com/a/9693933/179024

Der Kommentarthread unter dieser Antwort ist eine Lektüre wert, und ich teile auch einige Gedanken dazu in einer Antwort weiter unten auf derselben Seite:

https://stackoverflow.com/a/18381836/179024

3
MW.

Es tut mir leid, dass ich es als 'Antwort' angegeben habe, da ich noch nicht genug Punkte habe, um einen Kommentar abzugeben.

Bei unserer AngularJS-App sind wir auf ähnliche Probleme gestoßen. Bei der Verwendung von 'batarang' scheint es, als müsse mit einer großen Anzahl von Bereichsobjekten umgegangen werden, und ihre relevanten $ watch-Ausdrücke verursachen einen Leistungsabfall. Aus diesem Grund haben wir uns gefragt, ob stattdessen ein anderes Framework oder so etwas wie ReactJS verwendet werden sollte, um den View-Teil zu erledigen.

2
5122014009

vermeiden Sie Folgendes

  1. vermeiden Sie die Verwendung von ng-repeat, wenn Sie mehr als 50 Elemente gleichzeitig in der Liste haben, und vermeiden Sie manuelle Uhren
  2. verwenden Sie ng-click, ng-mouseenter, ng-mouseleave usw. Mausereignisse nicht blind, bis dies dringend erforderlich ist. Versuchen Sie, ihre Anzahl zu reduzieren, indem Sie $ event object zusammen mit den Ereignisverbreitungskonzepten von js verwenden

  3. verwenden Sie, wo immer möglich, scope. $ digest anstelle von scope. $ watch, um sicherzustellen, dass der Digest-Zyklus nur für die untergeordneten Bereiche ausgeführt wird

    1. versuchen Sie, verschachtelte Bereiche zu haben, d. h. einen oder zwei Controller innerhalb eines übergeordneten Controllers, und halten Sie die wiederverwendbare Logik im übergeordneten, ich habe dies in verschachtelten Zuständen verwendet, während Sie Ui-Router verwenden (um eine Anforderung zu erfüllen, bei der eine Änderung der URL ohne Seitenaktualisierung erforderlich war).

    am wichtigsten! ENTFERNEN SIE ALLE FILTER AUS HTML!

alle oben genannten Aktionen lösen einen Digest-Zyklus in allen Bereichen Ihrer Anwendung aus, sodass die Wahrscheinlichkeit hoch ist, dass auch nach dem Rendern der Ansicht angular) erneut unerbittliche Digest-Schleifen ausgeführt werden

2
Rishul Matta

Ein Mittelweg zwischen der Verlagerung der DOM-Manipulation in benutzerdefinierte Direktiven und den $ watch-Problemen mit vielen $ watches ist die Verwendung der Semantik "einmal binden".

Dies ist ideal für Daten, die unveränderlich sind, sobald die Daten verfügbar sind. Siehe bindonce

1
user239558

Dies wird nur ein Link sein! Dies ist nur eine Idee, die ich hatte, als ich dies las. Ich habe dies noch nicht untersucht, aber wahrscheinlich hat es jemand getan. Ich warte auf die Antwort auf meine Idee. Wie wäre es, wenn Sie gemeinsam genutzte Web-Worker verwenden, um den Benutzeroberflächen-Thread stark zu bearbeiten? https://github.com/h2non/sharedworkers-angular-poc

Die andere Idee, die ich hatte, war einfacher. Würde Ihre App vom unendlichen Scrollen profitieren? Ich meine, diese Formulare passen wahrscheinlich nicht alle auf den Bildschirm, sie sind nicht miteinander verbunden. Warum sollten Sie sie nicht so zeichnen, wie sie gebraucht werden? Laden Sie sie in den Speicher und zeichnen Sie sie entsprechend.

0
Zoneh

Wie bei jeder anderen Leistungsoptimierung ist es wichtig zu wissen, wie die Anwendung profiliert wird, um den tatsächlichen Engpass zu finden. Dann können Sie sie einzeln lösen. Normalerweise bekämpfe ich die Engpässe in der folgenden Reihenfolge:

  • mein Javascript-Code
  • winkelausdrücke (komplexe Beobachter und Filter), die in jedem Digest-Leerlaufzyklus ausgeführt werden
  • eckige Konstrukte (ng-repeat, Objekte für Digest-Zyklus kopieren)

Ich habe ein angular Beispiel Schritt für Schritt erstellt, in dem gezeigt wird, wie bei jedem Schritt ein Engpass festgestellt wird. http://bahmutov.calepin.co/improving-angular-web-app- performance-example.html

0
gleb bahmutov