Suchmaschinenoptimierung

SEO – Optimierung Teil 3/5

Reduzierung von HTTP-Anfragen

Im letzten Teil ging es u.a um die Reduzierung der HTTP-Anfragen. In diesem Teil wollen wir die verschiedenen Methoden betrachten und auf die jeweiligen Eigenschaften eingehen. Die Reihenfolge der Oprimierungen wurde frei gewählt, zum Schluss werden wir noch eine Top 5 Liste der besten Optimierungen für HTTP-Anfragen zusammenstellen.

PERFORMANCEGEWINN DURCH KOMBINIEREN/KOMPRIMIEREN

Das Kombinieren von Dateien wird häufig bei CSS- und JavaScript-Elementen angewendet. Für den Entwickler macht es Sinn, während der Entwicklung mehrere Dateien zu besitzen, um somit Modularität und Übersichtlichkeit zu wahren. Beim Laden der Webseite ist es jedoch nicht performant zahlreiche verschiedene Dateien zu laden und so die Anzahl der HTTP-Anfragen anschwellen zu lassen.

Bei der Kombination von JavaScript gibt es zwei verschiedene Ansätze. Der erste besteht darin, sich während der Entwicklung keine Gedanken zum Kombinieren der Daten zu machen und nur eine Referenz zu einer Skriptdatei anzugeben, welche bei jedem Aufruf der Seite geladen wird. Auf diese Art werden die JavaScript-Dateien zusammengefasst und in einer großen Datei zurückgeliefert. Dieser Ansatz wird auch als ad-hoc-Verfahren bezeichnet. Der zweite Ansatz besteht darin, die JavaScript Dateien bereits im Vorfeld zu kombinieren und als eine große Datei zur Verfügung zu stellen. Bei diesem zweiten Ansatz sind, sowohl die Belastung des Servers, als auch die Ladezeit niedriger als bei der ad-hoc-Variante.

Grafiken lassen sich ebenfalls, zu sogenannten Sprites zusammenfassen, wodurch die HTTP-Anfragen reduziert werden können. Bei dieser Technik werden verschiedene Bilder zu einem großen Bild zusammengefasst und dieses wird dann einmalig geladen und zur Verfügung gestellt. Mittels CSS Befehlen wird nur der Ausschnitt des Bildes gezeigt, der an der jeweiligen Stelle zu sehen sein soll. Es gibt verschiedene Wege Sprites zu erstellen, der performanteste ist mit Bildern im PNG-Format, deren enthaltene Elemente horizontal angeordnet sind. Durch diese Anordnung werden die Grafiken Algorithmus-bedingt kleiner.

PERFORMANCEGEWINN DURCH MINIMIEREN

Das Ziel der Minimierung ist es, die Dateigröße zu verringern, indem unnötige Informationen aus den Dateien entfernt werden. Darunter fallen beispielsweise nicht benötigte Leerzeichen, Tabulatoren, Zeilenumbrüche und Kommentare. Diese Dateien werden meistens als „minified“ bezeichnet. Bei der JavaScript-Bibliothek jQuery ist sehr schön zu erkennen, was eine solche Minimierung ausmachen kann. Die aktuelle Version 2.1.0 hat im Normalzustand eine Dateigröße von 240KB, nach der Minimierung beträgt die Größe nur noch 82KB. Es wird also durch die Minimierung 158KB pro HTTP-Anfrage eingespart. Sofern die minimierte Datei auch noch am Seitenende eingebunden ist, kann diese im Browser schneller verarbeitet werden. Ebenfalls bietet sich bei JavaScript eine Reduzierung der Variablen- und Methodennamen an.

Seit HTML4 können ebenfalls Einsparungen an den HTML-Tags vorgenommen werden. Die sogenannten „self closing“ Tags sind Tags die nicht explizit geschlossen werden müssen. Das spart Größe und kann die Performance um 5-20% verbessern. Das Weglassen von überflüssigen Attributen, wie beispielsweise nichtgenutzte IDs oder dem type=“text“ Attribut bei Eingabefeldern, birgt ebenfalls ein Einsparungspotential.

PERFORMANCEGEWINN DURCH AUSLAGERUNG

Der eigene Server kann durch das Auslagern von Schriftarten und JavaScript-Dateien entlastet werden. Vorweg muss gesagt werden, dass der größte Nachteil solcher Auslagerungen die Abhängigkeit der Seiten ist, von denen die Dateien dann bezogen werden. Google bietet beispielsweise alle seine Web-Fonts zur Onlineintegration an. Über den CSS-Befehl „@import url(http://fonts.googleapis.com/css?family=Revalia);“ wird die Schriftart direkt über den Google Server bezogen.
Ein weiterer Dienst in diesem Zusammenhang ist der Google Loader. Dieser Dienst ermöglicht das dynamische und schnelle Laden von einigen JavaScript-Frameworks, wie jQuery oder MooTools. Google übernimmt das Hosting der Anwendungen und verringert somit den Traffic auf dem Server. Um den Google Loader zu benutzen, bindet man an erster Stelle den Aufruf <script type=“text/javascript“ src=“/https://www.google.com/jsapi“></script> ein. Danach kann man die gewünschten Scripte wie im folgenden Beispiel zu sehen ist laden.

CACHING

Ein weiterer Ansatz HTTP-Anfragen zu verringern ist das Caching. Man versucht so viele Daten wie möglich im Cache zwischen zu speichern, sofern diese sich nicht ändern. In Webprojekten gibt es mehrere Stellen an denen man, mittels Caching, die Performance verbessern kann. Diese Stellen, welche wieder über verschiedene Techniken zum cachen verfügen, sind der Client, die Datenbank und die Anwendung selbst. Clientseitig gibt es viele Methoden die Performance zu steigern, vom Ausnutzen des Browser-Caches über das Verwenden von Cookies bis hin zu Web SQL und Indexed Databases. In diesem Abschnitt werden mit dem Anwendungscache und dem Web Storage zwei Methoden von aktuellen Browsern vorgestellt.

Der Web Storage wurde vom W3C-Konsortium entworfen und standardisiert. Er gibt an, wie Daten in einer Webanwendung, persistent auf der Clientseite, gespeichert werden. Im Gegensatz zu Cookies können die Dateien des Web Storage nur von clientseitigen Skripten geschrieben und gelesen werden. Der Vorteil ist, dass die Informationen nicht wie bei Cookies mit jeder HTTP-Anfrage zum Server gesendet werden. An dieser Stelle ist anzumerken, dass die Größe des Web Storage von Browser zu Browser unterschiedlich ausfällt und die enthaltenen Daten beim initialen Aufruf der Seite geladen werden, ob sie benötigt werden oder nicht. Entwickler müssen also darauf achten, den Web Storage wirklich nur als eine Art Cookie-Ersatz zu sehen und müssen dafür sorgen, dass nicht benötigte Dateien gelöscht werden.
Eine weitere Caching-Methode wird von HTML5 zur Verfügung gestellt. Der sogenannte Anwendungscache bietet die Möglichkeit, Ressourcen mittels einer serverseitig gesteuerten Konfigurationsdatei, in einen speziellen lokalen Cache zu legen. Diese Manifest-Datei regelt, welche Ressourcen in den Cache gelegt werden, welche nur online erreichbar sein sollen und enthält Fallback-Lösungen. Das besondere daran ist, dass die Ressourcen komplett im Offline-Modus zur Verfügung stehen. Das Laden der Ressourcen aus dem Anwendungscache entlastet den Server und sorgt für eine schnellere Antwortzeit. Manifest-Dateien lassen sich nachträglich ohne großen Aufwand einbinden. Hierzu muss lediglich der bestehende HTML-Tag mit dem Attribut manifest ergänzt werden. Diese Methode reduziert die Anzahl der HTTP-Anfragen, die durch Cookies verursacht werden und bietet sich zum Auslagern von größeren Dateien an. Ein Nachteil ist, dass diese Methode momentan nur von aktuellen Browsern unterstützt wird und clientseitig keine Daten gespeichert werden können.

JAVASCRIPT OPTIMIERUNG – DIE VARIABLEN

In JavaScript müssen Variablen nicht deklariert werden. Das Nichtdeklarieren hat aber zur Folge, dass die Variable als global gesetzt wird. Das bedeutet, dass der Interpreter die komplette Scope Chain abläuft, um die Variable zu finden. Als erstes iteriert der Interpreter über alle lokalen Variablen. Wird er nicht fündig, iteriert er über alle globalen Variablen. Das Weglassen des var-Schlüsselwortes führt zu erheblichen Performanceproblemen und sollte vermieden werden. Eine weitere Möglichkeit um Performancegewinne zu erzielen, ist es Werte in Variablen zu cachen um zu verhindern, dass der Interpreter wiederholt die gleiche Arbeit leisten muss. Ein Beispiel wäre hier die Länge eines Arrays zu cachen, damit diese nicht bei jedem Durchlauf der Schleife neu berechnet werden muss. In aktuellen Browsern wie Chrome und Firefox macht sich das Cachen der Array-Länge kaum bemerkbar, führt man stattdessen die optimierte Variante mit dem Internet Explorer aus, kann man eine Steigerung der Performance beobachten.

Performanceverluste treten in JavaScript immer dann auf, wenn eine Variable in der Scope Chain vom aktuellen Ausführungsort weit entfernt ist. In diesem Fall muss der Interpreter alle lokalen Variablen untersuchen, anschließend über die globalen Variablen iterieren und zusätzlich im globalen Namensraum eine temporäre Scope erzeugen. All dies passiert bei jedem Aufruf. Es bietet sich also an weitentfernte Variablen in lokalen Variablen zwischen zu speichern. Ein Beispiel hierfür ist jQuery. Wird jQuery in einer Funktion öfters verwendet, so kann man sich den Lauf entlang der Scope Chain sparen, indem man einen Alias verwendet, um es somit in dem aktuellen Scope zu platzieren.

OBJEKTE UND SCHLEIFEN

Schon bei der Erzeugung von Objekten kann man die Performance steigern, in dem man anstatt Konstruktoren, Literale benutzt. Die Objekte werden erstellt in dem man einen Objektliteral in den JavaScript-Code einbindet. Dies ist eine Liste von Werten die in geschweiften Klammern stehen und durch Kommas getrennt sind. Bei Arrays werden anstatt der geschweiften Klammern, eckige Klammern benutzt. Array- und Objektliterale werden meistens als Initialisierer bezeichnet, da sie im Vergleich zu echten Literalen, Teilausdrücke mit Eigenschafts- und Elementwerten enthalten und somit keine elementaren Ausdrücke sind.

Das Potential zur Steigerung bei Schleifen ist in JavaScript enorm. Eine Schleife die zahlreiche Aufgaben parallel abwickelt, kann nicht performant sein, denn in einer Schleife sollte so wenig wie möglich getan werden. In einem weiteren Schritt sollte die Länge des Arrays oder des Objektes immer gecached werden, damit die Länge nur ein einziges Mal ermittelt wird und nicht bei jeder Iteration neu berechnet werden muss. Ebenfalls sollte versucht werden, weitestgehend auf Funktionen zurückzugreifen, die in der ECMA-262-Spezifikation im Strict Mode definiert sind. Bei Zählschleifen bietet es sich an, sofern möglich, auf eine while-Schleife zu setzen, denn hier stecken sowohl der Zähler als auch die Bedingung im gleichen Konstruktor. Wie bereits beim Abschnitt der Variablen erwähnt, sollten diese außerhalb der Schleife deklariert werden.

ASYNCHRONE VERARBEITUNG

Kurze Ladezeiten, Benutzerfreundlichkeit und dynamische Inhalte zählen zu den Hauptkriterien der meisten modernen Webseiten. Um dies zu erreichen, ist eine asynchrone Verarbeitung notwendig. Asynchrone Verarbeitung bedeutet allgemein betrachtet die Entkopplung zweier Komponenten, die voneinander abhängig sind, im Sinne von blockierender Ausführung und Wartezeit. Der Webserver benutzt Threads, um mehrere Anfragen parallel abarbeiten zu können, ohne dabei andere Abfragen zu blockieren. Im Browser kommt die asynchrone Verarbeitung hauptsächlich mittels Ajax zustande, welches es erlaubt, Inhalte dynamisch zu laden. Das dynamische Laden von Inhalten bedeutet, dass die Webseite geladen ist und während der Benutzer damit arbeitet, können Ressourcen wie Texte, Bilder, CSS- und JavaScript Dateien nachgeladen werden. Besonders bei JavaScript kann durch asynchrones Laden eine Steigerung der Performance erreicht werden, denn das Blockieren des Ladevorgangs bezieht sich nur auf das <script= src“http://….“> Element im HTML-Markup.