JavaScript gehört mittlerweile zum Standard-Repertoire eines jeden Entwicklers; es existiert kaum ein Bereich, der nicht durch Tools, Frameworks oder Best Practices abgedeckt ist. Dennoch gibt es einen Punkt, der vielen Entwicklern immer wieder Kopfschmerzen bereitet: die JavaScript-Performance.
(image: ©Shutterstock / funnyangel)
JavaScript-Performance ist ein heikles Thema. Frameworks nehmen zwar viel Arbeit ab, sorgen aber auch dafür, dass man die Basics gerne mal außer Acht lässt. Denn sowohl in bestehenden als auch in neu erstellten Web Applikationen schlummert meist großes Leistungspotenzial.
JavaScript-Performance
Dabei geht es nicht nur um die reine JavaScript-Performance, sondern auch auf die Schnittstellen zum Benutzer, wenn es um das Rendering der Inhalte geht, sowie die Kommunikation mit dem Server.
Es sollten nur die Informationen übermittelt werden, die wirklich für die Applikation relevant sind!
Auf den JavaScript Days 2016, die vom 10. bis 12. Oktober in Berlin stattfinden werden, beschäftigen sich Thorsten Rinne und Sebastian Springer in ihrem Workshop JavaScript-Performance ausführlich mit diesem Thema. Grund genug für uns, die beiden zu diesem Thema zu befragen und um einige Tipps zu bitten.
Ihr beschäftigt euch in Zeiten immer mächtiger werdender JavaScript-Engines intensiv mit dem Thema JavaScript-Performance. Wie viel fangen V8, Chakra und Co. ab?
Sebastian Springer: Durch die Konkurrenz zwischen den Browserherstellern sind einige hoch optimierte Engines entstanden. Das merkt man vor allem bei den internen Optimierungen, wie beispielsweise der Verlagerung der Garbage Collection Cycles in die Idle Times oder die Verwendung von Hidden Classes, die eine Applikation vor allem dann beschleunigen, wenn Strukturen wiederverwendet werden. Für mich als Entwickler ist das sehr bequem, weil ich mich nicht mit Mikrooptimierungen herumschlagen muss, sondern mich auf Lesbarkeit und Wartbarkeit konzentrieren kann.
Thorsten Rinne: Wie Basti schon erwähnt hat, ist die Zeit von Mikrooptimierungen eigentlich vorbei, es sei denn, man hat Pech und muss noch einen IE8 unterstützen – was aber heute mehr nicht zeitgemäß ist, da ja selbst Microsoft den Support für diesen alten Browser eingestellt hat. Durch die hohe Performance aller JavaScript-Engines kann man sich heute auf sauberen Source Code konzentrieren. Und seien wir ehrlich: 0,01 % mehr Performance kostet mehr Arbeitszeit als ein neues Feature.
Mikrooptimierungen in Schleifen und Objektzugriffen sind also nicht mehr der erste und einfachste Schritt? Ist die Sache mittlerweile komplizierter?
Sebastian: Ja, wie schon gesagt: die Zeit der Mikrooptimierungen ist eigentlich vorbei. Das Cachen von Schleifenvariablen bringt so wenig im Vergleich zu einem nicht optimierten Request oder einer falsch formulierten DOM-Operation. Bei den Applikationen, die ich in letzter Zeit gesehen habe, liegen die Probleme in den seltensten Fällen im JavaScript-Code selbst, sondern viel häufiger an den Schnittstellen zum Server (gerade beim initialen Laden der Applikation) oder an der Schnittstelle zum Benutzer bei der Visualisierung der Informationen.
Thorsten: Viel mehr Performance – vor allem bei mobilen Geräten – bringt inzwischen die Reduktion von Requests und die Menge an Daten, die zum Browser übertragen werden muss. Eine Seite mit super Responsive Webdesign ist trotzdem lahm, wenn ein Smartphone vorher mehrere MB an JavaScript- und CSS-Code laden muss. Themen wie „Above the fold“, also dem Laden der sichtbaren Daten, sollten hier mehr in den Fokus der Entwickler gerückt werden. Auch sollte überprüft werden, ob auch wirklich alles an CSS eines Frameworks wie Bootstrap an den Browser ausgeliefert werden muss.
Das Hauptproblem dürfte nach wie vor das DOM sein. Wie kann man die intensiven Neuberechnungen des DOM-Baums performanter gestalten?
Sebastian: Zuerst einmal sollte jeder Entwickler wissen, warum es überhaupt zu Repaints und Reflows kommt, und welche negativen Auswirkungen sie auf die Performance einer Applikation haben können. Und wenn erst einmal klar ist, dass das wiederholte Ändern von CSS-Eigenschaften oder das Einfügen einzelner Knoten keine wirklich gute Idee ist, dann weiß man auch schon, was man dagegen tun kann: Operationen zusammenfassen, dem Browser die Chance zur Optimierung geben, Werte in JavaScript-Variablen cachen und so die teuren Berechnungen vermeiden. Wenn einem das zu viel Arbeit ist, kann man natürlich immer noch auf Frameworks zurückgreifen, die einem hier einiges an Arbeit abnehmen. Allen voran ist hier natürlich React mit seinem ShadowDOM zu nennen.
Thorsten: Wie schon gesagt, als Entwickler sollte man immer wissen: weniger ist mehr! Weniger unnötige Tiefe im DOM, weniger CSS Code und einfache Selektoren bedeuten mehr Performance der Applikation. Auch sollte man sich immer überlegen, ob man diese tolle Animation benötigt oder ob es auch ohne geht.
Auf den JavaScript Days beschäftigt ihr euch in eurem Performance-Workshop unter anderem auch mit der Kommunikation zwischen Browser und Server – welche Tipps habt ihr hier für Entwickler parat?
Sebastian: Da gibt es einige Tipps. Es hängt aber vor allem davon ab, an welcher Stelle man optimieren möchte. Beim initialen Laden einer Applikation gilt (wenn man HTTP1 verwendet): ein Browser hat nur eine begrenzte Anzahl paralleler Requests; alles was darüber hinaus geht, muss warten. Das bedeutet, wenige große und optimierte Dateien. Im Produktivbetrieb haben Whitespaces und Kommentare (außer Lizenzinformationen) nichts verloren. Durch einen sauberen Buildprozess kann man solche Artefakte generieren und hat dann sehr wenig Stress.
Was viele Entwickler auch gerne vergessen: die Browser haben Caches, in denen statische, sich selten ändernde Dateien hervorragend aufgehoben sind. Bei dynamischen Daten zur Laufzeit einer Applikation gilt ähnliches: Es sollten nur die Informationen übermittelt werden, die wirklich für die Applikation relevant sind. Alles andere kann entweder schon beim Benutzer liegen oder auf Clientseite errechnet werden. Hier sollte man sich als Entwickler aber immer in einem vernünftigen Rahmen bewegen und immer auf eine gesunde Kosten-Nutzen-Relation achten.
Thorsten: Caching ist ein großes Thema, client- wie serverseitig. Heute ist häufig I/O das Problem; sei es eine langsame Netzwerkverbindung oder ein Performance-Problem in der Cloud. Serverseitig kann man auch immer so rechnen, dass Arbeitsspeicher 100 bis 1.000 Mal schneller als eine SSD oder HDD ist. Je mehr z.B. im Arbeitsspeicher serverseitig vorgehalten werden kann, desto schneller kann es dann an den Browser ausgeliefert werden. Und sind diese Daten dann auch noch so klein wie nötig und möglich, dann klappt auch die gute Performance. Mit einem sinnvollen Caching im Browser – wie von Basti beschrieben – bekommt man dann Web Applikationen, die schnell reagieren.
Die Entwickler-Tools der Browser übernehmen heute alles, um die Performance analysieren zu können.
Mit welchem Tool-Set kommt man den Performance-Problemen eurer Erfahrung nach am schnellsten auf die Schliche?
Sebastian: Die Entwickler-Tools seines Lieblingsbrowsers sind das beste Werkzeug, wenn es um eine schnelle Performance-Analyse geht. Je gravierender die Probleme werden, desto tiefer muss man natürlich graben, und irgendwann endet man in Memory-Dumps und CPU-Profiles. Aber auch das können moderne Browser leisten.
Thorsten: Die Entwickler-Tools der Browser übernehmen heute eigentlich alles, was man so braucht, um die Performance analysieren zu können. Während der Entwicklung verwende ich auch gerne Linter, die meinen Code automatisiert statisch analysieren und mich auf Probleme hinweisen. So meckert das NodeJS-Tool sass-lint beispielsweise ab einer bestimmten Tiefe von verschachtelten Selektoren.
Wenn ihr Entwicklern eine simple Checkliste zum Thema JavaScript-Performance, bestehend aus drei bis vier Punkten, mit auf dem Weg geben müsstet – welche Punkte wären das?
Sebastian:
- Operationen in Schleifen sind meist tödlich
- Ketten von einzelnen DOM-Operationen vermeiden
- Bei größeren Operationen: Knoten aushängen, Operation durchführen, Knoten in den DOM-Baum einhängen
- Immer ein Auge auf die Developer Tools haben
Thorsten:
- Ergebnisse der PageSpeed Insights beachten
- Netzwerktraffic beobachten und Anzahl Requests gering halten
- KISS: Keep it simple & stupid