Performance für Einsteiger, Teil 3: Frontend-Performance
Das Frontend der Webseite bietet eine Menge Optimierungsspielraum, den jeder Webworker ohne allzu große Anstrengungen ausnutzen kann. Im letzten Teil der Website-Performance-Wochenserie haben wir uns mit Latenzen, HTTP-Overhead und den Grundlagen der Reduktion von Verbindungen zur Optimierung der Webite-Performance auseinandergesetzt. Heute wollen wir uns um die Reduktion der Datenmenge kümmern, denn obwohl eine schlechtere Latenz viel stärkere Auswirkungen auf die Ladezeit unserer Seite hat, ist die zu übertragende Datenmenge ebenfalls ein wichtiger Faktor.
Im Folgenden stellen wir dir verschiedene Ansätze zur Datenreduktion vor, die alleine geringe Auswirkungen haben, aber in Summe in einer messbaren Verbesserung resultieren können.
Bilder optimieren
Bilder nehmen wohl den größten Teil der Gesamtmenge an Daten einer Webseite ein. Die Optimierung von Bildern spart wertvolle Kilobyte und somit Übertragungszeit. Die Optimierung beginnt bei der Wahl des richtigen Bildformates. Je nach Inhalt der darzustellenden Grafik, kann die Wahl des Formates entscheidend über die Dateigröße sein. Als Webworker stehen uns neben JPG, GIF und PNG auch SVG-Grafiken und das neue WEBP Format zur Verfügung. Letzteres wird zwar noch nicht weitläufig unterstützt, sollte aber dennoch nicht ungenannt bleiben.
Verschiedene Formate komprimieren verschieden gut, mit unterschiedlicher Bildung von Artefakten. Hier gilt meistens Probieren über Studieren. Benötigt man hochwertige Bilder mit Transparenten Flächen, kann man auf JPG und GIF in der Regel von Vorne herein verzichten. Dafür kann man ohne Bedenken bei der Darstellung eines sehr großen Bildes wohl grundsätzlich auf das JPG-Format zurückgreifen.
Neben der Auswahl des Formates, kann die Reduktion von Farben zu einem optisch kaum wahrnehmbaren, aber in der Dateigröße deutlich messbaren Unterschied führen. Auch die Verstärkung der Kompressionsstufe, während der Generierung eines JPG-Bildes, hilft Kilobyte bei vertretbarer Qualität einzusparen. Im obenstehenden Beispiel erreichen wir durch die Reduktion der Farben eine Kompression von 35 Prozent zum Originalbild.
Überflüssige Daten entfernen
Das Entfernen von Meta-Informationen in Bildern spart zusätzliches Gewicht ein. Immerhin können diese Informationen neben spannenden Werten wir Brennweite, Blende und Belichtungszeit auch komplette Vorschaubilder enthalten, die wir nun wirklich nicht für den Betrieb unserer Webseite benötigten können.
Meistens geben Grafik-Programme mit den entsprechenden Export-Einstellungen bereits gut optimierte Bilder aus. Mit einigen Online-Tools wie TinyPNG, JPEGmin oder dem „Image-Optimizer“ von Dynamic Drive können noch bessere Ergebnisse erzielt werden – vollautomatisch.
CSS statt Bilder
Für die Datenreduktion ist ein gänzlicher Verzicht auf Grafiken noch besser. Dank CSS3 haben wir deutlich bessere Möglichkeiten, um unser Design ohne Bilder zu gestalten. Das hat nicht nur Vorteile für die Datenmenge, sondern resultiert auch in einer besseren Unterstützung für Retina-Geräte. Die Berechnungszeit für CSS3 darf aber nicht unberücksichtigt bleiben. Besonders bei mobilen Geräten könnte dieser Ansatz also unter Umständen problematischer sein, als die Auslieferung von Bildern. Die nachfolgende Grafik des „Smashing-Magazine“ illustriert die Ladezeiten für bestimmte CSS3-Eigenschaften.
Minifying und Obfuscation
Auch Skripte und Stylesheets bringen einiges auf die Wage – aber auch an dieser Schraube können wir drehen. Zum einen können JavaScript- und CSS-Bibliotheken „minified“ &ndash, also verkleinert – werden. Hierfür werden alle Kommentare, Zeilenumbrüche und nutzlose „Whitespaces“ aus dem Dokument entfernt, um Kilobytes zu sparen. Dadurch entstehen für Menschen beinahe unlesbare Code, denn dieser wird in einer Zeile dargestellt. Für den Browser stellt die Schreibweise kein Problem dar, sodass die Verarbeitung problemlos erfolgen kann.
Mit „Obfuscation“ kann bei JavaScript zusätzlich die Dateigröße verringert werden. Bei dieser Technik werden Funktions- und Variablennamen umgeschrieben und in verkürzter Form dargestellt. So ist eine deutlich kompaktere Schreibweise bei gleichbleibender Funktionalität möglich.
Für die Verkleinerung und „Obfuscation“ eines Skriptes gibt es verschiedene Online Tools wie JSMin, den „YUI-Compressor“, „Minify“ und den „Closure-Compiler“.
Auch „Taskrunner“ wie „Grunt“ bieten euch diese Möglichkeiten. Wir helfen dir die ersten Schritte mit Grunt ohne Probleme zu meistern.
Die Verkleinerung bringt bei CSS in der Regel nicht so viel wie bei JavaScript. Hier optmiert man am besten von Hand und entfernt Redundanzen und unnötige Code-Fragmente. Hierbei kann eine verkürzte Schreibweise von Klassen oder Beispielsweise auch Farbwerten und Größenangaben einen Teil zur Leistungssteigerung beitragen. Das kann schnell in kleinteiliger Arbeit resultieren, sodass wie bei allen Optimierungsmaßnahmen, der Aufwand nicht den Nutzen überwiegen sollte.
Optimale Datenauslieferung mit Content-Delivery-Networks
Wie ist deine Webseite aufgebaut? Wahrscheinlich hast du irgendwo einen Webspace, einen V- oder Root-Server angemietet? Alle diese Lösungen haben eins gemeinsam: Du hast einen festen Serverstandort und somit je nach Herkunft des Besuchers einen längeren Datenweg. Je länger die Strecke, die zurückgelegt werden muss, desto mehr zwischenpunkte müssen durchquert werden und desto wahrscheinlicher ist auch der Anstieg der Latenz für die Auslieferung der Daten.
Content-Delivery-Networks arbeiten mit verteilten Servern und liefern die Daten von Servern aus, die so nah wie möglich am Kunden stehen (die so genannte „EDGE“). Hierfür wird eine Ortung des Users mit Hilfe seiner IP-Adresse vorgenommen und anschließend auf den jeweiligen Server verwiesen. Selbstverständlich stehen solchen Services auch deutlich höhere Bandbreiten, für die Verteilung der Ressourcen, zur Verfügung als einem eigenen Server oder gar einem Webhosting-Paket.
Content-Delivery-Networks sind für die Verteilung von statischen Ressourcen wie Bildern und andere Multimedia-Daten, Stylesheets und JavaScripts zuständig. Dein Webserver ist dann nur noch für die dynamischen Vorgänge und die Auslieferung des eigentlichen HTML-Dokumentes zuständig. So wird dein Server entlastet und eine teilweise deutlich schnellere Auslieferung deiner Inhalte ermöglicht.
Content Delivery Networks sind in der Regel aber keine günstige Angelegenheit. Bei Anbietern wie Akamai, Amazon oder Cachefly müsstest du mit Kosten, die im dreistelligen Bereich angesiedelt sind, rechnen.
„Google Hosted-Libraries“
Man muss nicht unbedingt tief in die Tasche greifen um die Vorteile eines Content-Delivery-Networks für seine Webseite nutzen zu können.
„Google Hosted-Libraries“ ist ein Teil der Google Initiative „Make The Web Faster“. Dabei stellt Google viele beliebte Bibliotheken wie jQuery, Angular.js oder Bootstrap auf dem Google eigenen CDN zur Verfügung.
Durch die Nutzung der Libraries reduzierst du den Traffic auf deiner eigene Webseite und du kannst die beachtliche Performance von Google ausnutzen. Zusätzlich sorgst dadurch, dass wenn die Bibliotheken bereits auf einer anderen Seite mit eingebundener „Google Hostet-Library“ gecached wurden, für eine zusätzliche Steigerung der Performance. Für eine solche Lösung lohnt sich der Einsatz eines Fallbacks für den Fall, dass die Content-Delivery-Network-Server von Google, aus irgendeinem Grund nicht erreichbar sein sollten. Die „HTML5-Bolierplate“ hält heirfür eine elegante Lösung parat:
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="js/vendor/jquery-1.10.2.min.js"></script>')</script>
Grundlagen der Rendering-Performance
Neben der Übertragungs-, spielt auch die Rendering-Performance einen wichtigen Teil für die „User-Experience deines Besuchers. Die Position von externen Ressourcen innerhalb des Dokuments, kann entscheidende Veränderungen bei der gefühlten Ladezeit bedeuten.
CSS am Anfang des Dokumentes
Das hängt mit der Handhabung solcher Ressourcen zusammen. Stellt der Browser fest, dass Stylesheets am Ende des Dokumentes eingefügt sind, beginnt er das Rendering erst, wenn auch diese Dokumente geladen wurden. Schließlich könnten, die bis dahin noch unbekannten Stylesheets, starke Veränderungen am Layout verursachen und in vorhergehenden Stylesheets definierte Eigenschaften überschreiben, sodass aus Browsersicht das Warten auf die Ressource besser ist, als ein überflüssiger Render-Vorgang.
Sind alle Stylesheets am Anfang des Dokumentes eingebunden, beginnt der Browser sofort mit dem Rendering, was in einer gefühlt besseren Ladezeit für den Benutzer resultiert.
JavaScript am Ende des Dokumentes
Noch interessanter ist das Handling von JavaScript. Anders als CSS sollte JavaScript immer – sofern die Programmlogik das zulässt – am Ende des Dokumentes positioniert werden. Erkennt der Browser, dass ein JavaScript geladen werden muss, stellt er die Arbeit an allen anderen Baustellen ein, bis das Skript geladen und ausgeführt ist. Schließlich könnte das Skript zahlreiche Änderungen am Dokument vornehmen und andere Skripte könnten auf einander aufbauen, sodass das „Einfrieren“ aller weiteren Vorgänge notwendig ist um die Programmlogik zu wahren.
Das kann unter Umständen zu sehr langen Renderzeiten führen. Durch die Positionierung am Ende des Dokumentes, wird dieses Verhalten ausgehebelt.
JavaScript performanter einbinden
Aber auch andere Techniken erlauben es JavaSkripte am Anfang des Dokumentes zu platzieren, ohne das Seiten Rendering zu blockieren. Mit dem defer
-Attribut kann dem Browser ein Hinweise gegeben werden, dass das Skript erst dann startet, nachdem die Seite geladen ist. Viele Browser ignorieren diesen Hinweis aber.
<script src="demo_defer.js" defer></script>
In HTML5 steht für diese Funktionsweise das async-Attribut zur Verfügung
<script async src="siteScript.js" onload="myInit()"></script>
Da auch die Abarbeitung des async
-Attributes nicht garantiert ist, kann man das Verhalten mit diversen „Loader“-Bibliotheken erzielen. Mit Bibliotheken wie „Head.js“, „Control.js“ und „Require.js“ können Skripte asynchron und parallael geladen, aber dabei dennoch in der richtigen Reihenfolge ausgeführt werden, sodass ein Blockieren des Renderings vermieden und die Ladezeit durch Parallelisierung optimiert wird. Außerdem bringen solche Lösungen weitere Vorteile wie eine saubere modulare Trennung und Reduktion von Namenskonflikten mit sich.
Inline-Frames als Performance-Killer
Jedes „Tag“ im DOM benötigt eine gewisse Zeit um generiert zu werden. Ein ganz bestimmtes Element sticht jedoch besonders aus der Masse heraus. Für die Erzeugung eines „Iframe“-Tags benötigt der Browser deutlich länger als für andere Auszeichnungselemente unserer Webseite.
Die obenstehende Grafik illustriert, wie weit die Auswirkungen auf die Performance, durch den Einbau eines „Inline-Frames“ auf mobilen Geräten, wirken. Selbiges gilt natürlich auch für Desktop-Geräte. Denn „Inline-Frames“ blockieren das „OnLoad-Event“ der Seite, sodass der Browser so lange wartet, bis auch der letzte „Iframe“ geladen ist, bevor das Ereignis ausgelöst wird. Wenn du nicht auf „Inline-Frames“ verzichten kannst, sollten diese zumindest nach Möglichkeit dynamisch mit JavaScript generiert werden, um nicht den Rest deiner Seite zu blockieren.
Natürlich bringt ein „Iframe“ auch Vorteile. Da „Iframes“ quasi als Browserfenster innerhalb eines Browserfensters existieren, werden Ressourcen in „Iframes“ parallel zu restlichen Seitenbestandteilen geladen. Das wiederum resultiert in einem gewissen Performance-Boost. Da die Hauptseite und der „Iframe“ einen gemeinsamen Verbindungs-Pool haben, also ein gemeinsames Verbindungslimit, lässt sich daraus nur bis zu einem bestimmten Grad eine verbesserte Performance ableiten.
Fazit
Es kommt eben doch auf die Größe an – die Reduktion von Dateigrößen ist ein wesentlicher Bestandteil der Frontend-Optimierung und kann zu erheblich verbesserten Ladezeiten führen. Aber auch die Verarbeitung der Daten im Browser selbst ist ein wichtiger Baustein für schnelle Ladezeiten. Hier gilt es die Reihenfolge, in der Ressourcen geladen werden, zu optimieren und „Blocker“ zu vermeiden.
Einige Tipps und Tricks mit denen du serverseitig die Performance deiner Webseite steigern kannst und welche Möglichkeiten der Server in Sachen Performance zu bieten hat, verraten wir dir im nächsten und letzten Teil dieser Serie. Hier kommst du zuürück zum zweiten Teil dieser Serie.
Hier findest du alle bisherigen Teile der Performance Serie:
- Performance für Einsteiger, Teil 1: Performance-Analyse
- Performance für Einsteiger, Teil 2: Requests reduzieren, Geschwindigkeit erhöhen
- Performance für Einsteiger, Teil 4: Dein Server kann mehr