Eine Seite zu erstellen ist eine Sache. Die Seite schnell, performant und für hohe Lasten tauglich zu machen, ist wieder eine eigene Wissenschaft.

Grundlegend bei der Optimierung gilt, dass man aus einem LKW keinen Rennwagen machen kann. Die absolute Grundlage ist also eine schlanke Code-Basis, die keine unnötigen Dinge lädt (siehe meine tweak-Sammlung) und auch die Bilder nicht zu groß sind (Tipp: WP-Smush für WordPress) – und dies ist weitaus günstiger als leistungsfähigere Server :-D. Leider ist „mehr Hardware-Leistung“ manchmal die einzige mögliche Lösung …

Danach kommt die Optimierung der Prozesse, die zwischen dem Klick auf ein Link oder der Eingabe einer Adresse in die Adresszeile und der fertig geladenen Seite geschehen. In diesem Bereich gibt es eine Vielzahl von Tipps und Tricks, ich möchte hier nur auf ein paar ausgewählte Maßnahmen eingehen, die mit sehr wenig Aufwand einen großen Effekt bringen.

Vor der Optimierung steht auch immer die Messung, mit der wir das Ergebnis unserer Arbeit kontrollieren. Dazu gibt es mehrere Möglichkeiten, zum einen mächtige externe Tools wie z.B. GTMetrix – hier wird die Seite geladen und der Nutzer erhält zahlreiche Verbesserungsvorschläge. Achtung: Ein hoher Score heißt noch lange keine schnelle Seite! Auch machen nicht alle vorgeschlagenen Maßnahmen für alle Anwendungsfälle Sinn, hier benötigt es tieferes Verständnis der Zusammenhänge, um differenziert beurteilen zu können, welche Empfehlung von GTMetrix wirklich wert ist umgesetzt zu werden, oder welche man einfach ignorieren kann. Attraktiv ist auch das automatische Monitoring (im freien Tarif 1 Scan pro Tag mit wöchentlichen E-Mail-Berichten) der Seite, wo man über lange Zeiträume sehen kann, wie sich die Seite in Sachen Ladezeit und Performance verhält.

Wer es schlanker haben will, kann mit Debug-Tools wie das Firefox Plugin Firebug mit dem Netzwerk-Tab das Ladeverhalten der Seite messen. Hier werden alle Ressourcen der Seite und ihre Ladezeit aufgelistet (hier die Startseite meiner Webseite):

firebug

[Ja, meine Internetleitung ist bei dieser Messung belegt gewesen, aber so sieht man wenigstens die Ladebalken :-D]

Nachdem wir wissen, wie wir messen und kontrollieren könne, eine schlanke Code-Basis haben (oder wissen, dass sie nicht schlanker möglich ist/sein soll z.B. weil man ein ganz bestimmtes Theme so verwenden möchte) hier ein paar effiziente Möglichkeiten der Optimierung:

Server: http/2

Im sog. Wasserfall-Diagramm oben sieht man sehr übersichtlich, welche Ressourcen geladen werden, wie groß sie sind und wie lange sie dazu benötigen. Anmerkung: Die Webseite läuft unter https und der Server beherrscht das http/2-Protokoll, deswegen laden alle initial geladenen Ressourcen gleichzeitig. Bei http/1.1 konnten maximal 4 Ressourcen pro Domain gleichzeitig übertragen werden. Bei Seiten mit vielen Ressourcen stellt http/2 also eine enorme Performance-Verbesserung dar.

 

Server: SSD-Festplatten

Der genutzte Server für diese Webseite besitzt SSD-Festplatten. Im Gegensatz zu Festplatten mit gedrehten Scheiben ist hier die Schreib- und Leserate erheblich höher – wer einmal einen Rechner mit SSD-Festplatte benutzt hat, kennt den Effekt 😉

Die Preise für SSD fallen immer weiter und damit steigt auch die Verbreitung. In 10 Jahren werden wir vielleicht über gedrehte Scheiben in Festplatten lachen – wer weiß?!

 

Gzip-Kompression

Vor der Übertragung kann man Dateien verschlüsseln, womit sie die zu übertragende Dateimenge reduzieren und die Ladezeit ebenfalls reduzieren. Dies geht mit folgendem Code in der .htaccess auf Apache-Webservern:

<IfModule mod_deflate.c>
  # Compress HTML, CSS, JavaScript, Text, XML and fonts
  AddOutputFilterByType DEFLATE application/javascript application/rss+xml application/vnd.ms-fontobject application/x-font application/x-font-opentype application/x-font-otf application/x-font-truetype application/x-font-ttf application/x-javascript application/xhtml+xml application/xml font/opentype font/otf font/ttf image/svg+xml image/x-icon text/css text/html text/javascript text/plain text/xml

  # Old Mozilla Browser problems
  BrowserMatch ^Mozilla/4 gzip-only-text/html
  BrowserMatch ^Mozilla/4\.0[678] no-gzip
  # MSIE problems
  BrowserMatch \bMSIE !no-gzip !gzip-only-text/html
  #Proxy delivery fix
  Header append Vary User-Agent env=!dont-vary
</IfModule>

VORSICHT: Nicht alle Hoster unterstützen gzip-Kompression. Des weiteren kann je nach Seite die Kompression zu Problemen führen. Falls sich das Problem auf eine einzelne Seite/Ordner bezieht, kann dieser mit folgendem Code in der .htaccess ausgenommen werden:

SetEnvIf Request_URI ^/ordner-ohne-gzip/ no-gzip=1

Ein sorgfältiger Test ist hier auf jeden Fall nötig. Bereits komprimierte Dateien (mp3, jpg, …) können nach der Kompression jedoch größer sein als vorher. Diese werden deswegen auch nicht in die AddOutputFilterByType Liste mit aufgenommen. Auch können sehr kleine Dateien nach der Kompression größer als vorher sein.

Des weiteren kostet die Gzip-Kompression etwas mehr CPU-Last auf der Serverseite, dies ist es jedoch gegen den Gewinn an Performance auf jeden Fall wert.

Browser Cache

Der Webbrowser hat einen internen Zwischenspeicher (Cache), in dem Ressourcen gespeichert werden können, damit sie beim erneuten Besuch der Seite oder laden einer weiteren Seite nicht jedes Mal neu geladen werden müssen. Dies führt zu einer enorm sinkenden Serverlast und bei langsamen Internetanschlüssen zu einem deutlich schnelleren Seitenaufbau. Mit folgendem Code in der .htaccess (Apache Webserver) der Webseite kann man den Cache aktiv steuern – standardmäßig tun dies viele CMS wie z.B. WordPress, Magento und andere NICHT!

<IfModule mod_expires.c>
    ExpiresActive On
    ExpiresByType image/jpg "access 1 week"
    ExpiresByType image/jpeg "access 1 week"
    ExpiresByType image/gif "access 1 week"
    ExpiresByType image/png "access 1 week"
    ExpiresByType text/css "access 1 week"
    ExpiresByType text/html "access 1 week"
    ExpiresByType application/pdf "access 1 week"
    ExpiresByType text/x-javascript "access 1 week"
    ExpiresByType application/x-shockwave-flash "access 1 week"
    ExpiresByType image/x-icon "access 1 week"
    ExpiresDefault "access 1 week"
</IfModule>

Hier wird also je nach Dateityp eine unterschiedliche maximale Vorhaltedauer im Cache festgelegt. ACHTUNG: Änderungen an den Dateien (z.B. in den CSS-Ressourcen oder Bilder) werden so erst nach der angegebenen Zeit für den Nutzer sichtbar (hier 1 Woche), wenn sich der Cache nicht automatisch leert! Dies kann zu enormen Darstellungsfehlern beim Nutzer führen, bei größeren Updates kann man sich behelfen, indem man z.B. wichtige Ressourcen umbenennt (falls möglich), oder die Lebensdauer im Cache vorher absenkt.

Beispiel an meiner Webseite: Das oben gezeigte Wasserfall-Diagramm zeigt den Ladeprozess meiner Startseite ohne Cache (34 Abfragen, 644 kB). Mit Cache und vorher besuchter Seite sieht es folgendermaßen aus:

firebug2

2 Anfragen und weniger als 1 kB, die durch die Leitung transferiert wurden. Der Browser Cache ist ein enorm wichtiger Helfer, um die Anzahl der Serverabfragen und die Ladezeit gering zu halten.

 

Vorsicht bei …

Ressourcen mergen: Gerne wird behauptet, dass die Zusammenführung von CSS und JS-Dateien zu einer besseren Performance führt, da hier die Serverabfragen reduziert werden, auch Werkzeuge wie GTMetrix sehen dies gerne bzw. merken an, wenn es viele JS/CSS-Ressourcen gibt. Aber: Webseiten Performance ist ein Gesamtpaket und hier muss der mögliche Weg des Nutzers über die gesamte Webseite berücksichtigt werden. Beispiel:

  1. Ein Nutzer besucht die Startseite, alle Ressourcen werden geladen und im Cache gespeichert.
  2. Klick auf einen Artikel. Nun wird noch die Datei artikel.js und artikel.css geladen, der Rest kommt aus dem Cache.
  3. Klick auf die Suche, hier kommen weitere CSS und JS Dateien hinzu, der Rest kommt wieder aus dem Cache.
  4. … das Spiel ließe sich beliebig fortsetzen.

Dazu ist zu beachten, dass es hier nicht um eine einzelne Datei geht, die auf bestimmten Seiten zusätzlich geladen wird, sondern um zig Dateien. Der Aufruf einer Magento2-Kategorieseite hat zum Beispiel in einem Shop, der kaum angepasst, gar nicht optimiert wurde und sehr nah an der Magento2-Standardvariante gehalten ist, ca. 110 Server requests. Davon entfallen alleine 5 auf CSS und ca. 75 auf JS!

Wenn man nun alle CSS und JS Ressourcen auf der Webseite zu einer Datei zusammenführt, muss zwar zwar nur eine Datei geladen werden, die enthält aber je nach Struktur der Seite Inhalte, die der Nutzer gar nicht benötigt und sie ist wesentlich größer, als die in Schritt 1 geladenen Dateien – und wenn es schlecht läuft, wird auf jeder Seite ein anderes „all in one“-Kombinat geladen, was die Gesamtmenge an übertragenen Daten unnötig groß macht.

Die Lösung zum mergen von CSS/JS

Die ideale Lösung (aber nicht immer möglich) besteht darin, eine kombinierte css- und js-Datei zu erstellen, in der alle Komponenten enhalten sind, die auf jeder Seite geladen werden. Dann kombiniert man alle zusätzlichen Dateien, die nur auf einzelnen Seiten wie z.B. einem Warenkorb, Checkout oder anderen Seiten benötigt werden. So hält man die nötigen Serverabfragen so klein wie möglich und hält die zu ladende Dateimenge über alle Seiten hinweg so klein wie möglich, da die Komponeten, die auf jeder Seite geladen werden, natürlich aus dem Browser-Cache geladen werden. Ein Beispiel für Magento 1 wäre das Plugin Speedster Advanced von Fooman.

Kleinkram macht auch Mist

Minify bezeichnet die Minifizierung und Reduzierung von Dateien. Unnötige Leerzeichen und Umbrüche werden entfernt. Dadurch werden die Dateien nur noch schwer lesbar und die Dateigröße sinkt um wenige Prozent. Wer es mag, kann sich gerne damit beschäftigen … in meinen Augen aber eher weniger wichtig.

 

CMS Plugins

Einige CMS wie z.B. WordPress bieten zahlreiche Plugins zur Performance-Optimierung, aber auch hier ist meine Meinung, dass nicht jedes Plugin wirklich nötig ist und meist mit ein wenig Code recht schlank zu ersetzen ist. Zudem muss man auch für Plugins wie z.B. Super Cache oder W3 Total Cache ein Verständnis von der Materie haben, denn einfach blind alles anzuhaken oder die Standardkonfiguration zu übernehmen führt mit sehr hoher Warscheinlichkeit NICHT zum optiomalen Ergebnis.