Share- & Like-Buttons selber hosten und designen

Die Share- und Like-Buttons von Google, Facebook, Xing, Twitter, Linkedin und all den anderen sozialen Netzwerken sind mit kleineren Hürden schnell auf der eigenen Webseite integriert. Was ist das Problem? – Die Buttons laden langsam, sind datenschutzrechtlich bedenklich, sehen alle unterschiedlich aus und passen – egal wie man es dreht und wendet – nicht so recht ins Design. Eine andere Lösung muss her!

Layout / Designprobleme

Zunächst einmal das Offensichtliche: Unstrittig ist, dass die Buttons (ob von Google, Facebook, Xing, Twitter, Linkedin oder wem sonst) nur mit einer begrenzten Anzahl an Layoutentwürfen daherkommen. Daher passen diese zumeist auch nicht oder nur begrenzt in das eigene Webdesign von 2015. Ein weiteres Design-Problem ist, dass die Anbieter sich nur begrenzt auf ähnliche Layouts einigen konnten. Ob Hintergrund mit oder ohne Verlauf, der Border-Radius oder elementare Dinge wie die pixelgenaue Höhe – deprimierend.

Ladehemmungen

Mithilfe der nativen Integration werden die Buttons mit mehreren Aufrufen von den Seiten des Anbieters geladen. Für Twitter, Facebook und Xing mit 19 Requests dauert dies ca. 1-2 Sekunden und bedeutet 19 Ressourcen, die geladen werden müssen. Das sind mehr Elemente als die gesamte Webseite bzw. ein einzelner Blogbeitrag in Summe hat.

Bei mäßigem Surfverhalten und ausgehend von der Tatsache, dass nicht jede Webseite Share-Icons anbietet, müssen zumeist DNS-Anfragen vorab getätigt werden. Das kostet zusätzlich Zeit. Da nicht jeder Dienst zu jeder Tageszeit gleichermaßen performant ist oder hin und wieder auch mal komplett hängt, legt man das Design der Seite – mit der Nutzung eines Share-Icons – in die Hand des jeweiligen Anbieters.

Datenschutzrechtlich bedenklich

Löblich und gesetzeskonform ist, wenn in Ihren Datenschutzbestimmungen die Integration der einzelnen Services erwähnt ist. Aber: Hand aufs Herz. Haben Sie diese Bestimmungen schon einmal gelesen und verstanden? Sind diese Bestimmungen aktuell und nach geltendem Recht?


Wenn Sie diese Frage mit einem klarem „Ja“ beantworten können: Chapeau!
Ansonsten geht es Ihnen ungefähr wie mir: obwohl ich mich mit der Thematik des Datenschutzes ausführlich beschäftige, kann ich nicht mit absoluter Sicherheit sagen, ob dem Landesrecht, dem deutschem Recht oder/und europäischem Recht damit genüge getan wird. Dispute mit den einzelnen Konzernen gibt es zur Genüge und eine besondere Affinität zum Datenschutz hat auch keiner dieser Konzerne, schließlich sind Daten deren Geschäftsgrundlage. De facto holt man sich eine oder mehrere Datenkraken auf die eigene Webseite.

Wir Webmaster legen in diesem Moment die Verantwortung in die Hand unserer Seitennutzer. Diese müssen proaktiv und vorab entsprechende Ressourcen blockieren, ohne zu wissen, dass diese auf unserer Seite sind. Die im Datenschutz geforderte informationelle Selbstbestimmung ist damit (ohne das nun weiter auszuführen) mehr Schein als Sein.

Die Lösung

Damit wir Webmaster auch wieder Herr der Daten werden, ist es erforderlich, dass die Daten (wie die Anzahl der Likes oder Shares) selbst erhoben werden. Hierhingehend stellen die verschiedenen Dienste APIs bereit, mit denen die Daten gesammelt werden können.

Jeder Anbieter hat zumeist einen Link, über den direkt die URL geteilt werden kann. Diese zwei Techniken bringe ich im Folgenden zusammen.

Zunächst haben ich dabei die Butttons mit einheitlichem Syntax erstellt und gestylt:

HTML-Chunk

<div class="share" style="padding-top:15px"> <span class="share_counter" style="display:none">Interaktionen - Vielen Dank!</span><br><br> <a href="https://www.facebook.com/sharer/sharer.php?u={url}" title="Teile den Beitrag {titel} mit Facebook" class="btn btn-default btn-facebook btn-share"><span class="flaticon-facebook"></span> <span class="text">like it</span></a> <a href="https://twitter.com/home?status={url}" title="Teile den Beitrag {titel} mit Twitter" class="margin-left btn btn-default btn-twitter btn-share"><span class="flaticon-twitter"></span>  <span class="text">tweet it</span></a> <a href="https://plus.google.com/share?url={url}" title="Teile den Beitrag {titel} mit Google +" class="margin-left btn btn-default btn-google btn-share"><span class="flaticon-google"></span>   <span class="text">give it +1</span></a> <a href="https://www.xing.com/spi/shares/new?url={url}" title="Teile den Beitrag {titel} mit XING" class="margin-left btn btn-default btn-xing btn-share"><span class="flaticon-xing"></span> <span class="text">share it</span></a> <a href="mailto:?&subject=Linkempfehlung&body;={url}" title="Teile den Beitrag {title} per E-Mail" class="margin-left btn btn-default btn-mail"><span class="glyphicon glyphicon-envelope"></span>   Weiterleiten</a></div>

CSS-Code

Da wir Bootstrap und Favicons von flaticon.com einsetzen, ist der Aufwand nur marginal

.btn-default {
    font-family: 'League Gothic', sans-serif;
    background: none;
    font-size: 24px;
    color: #333;
    border-color: #666;
    transition: all 0.3s ease;
}
.btn-default:hover {background: #333; color: #fff;}
.btn-default:focus {outline:0;}
.btn-xing:hover { color: #338383; border-color: #338383; background: none; }
.btn-xing { background: #338383; border-color: #338383; color: #fff; }
.btn-google:hover { color: #db4a39; border-color: #db4a39; background: none; }
.btn-google { background: #db4a39; border-color: #db4a39; color: #fff; }
.btn-twitter:hover { color: #00acee; border-color: #00acee; background: none; }
.btn-twitter { background: #00acee; border-color: #00acee; color: #fff; }
.btn-facebook:hover { color: #3b5998; border-color: #3b5998; background: none; }
.btn-facebook { background: #3b5998; border-color: #3b5998; color: #fff; }
.btn-mail:hover { color: #999; border-color: #999; background: none; }
.btn-mail { background: #999; border-color: #999; color: #fff; }

Javascript

Weiter wird ein wenig JavaScript benötigt, der zunächst die Button-Klicks in Popups aufruft:

    $('a.btn-share').on('click', function(event) {
        // Popup öffnen und Fokus setzen
         fenster = window.open($(this).attr('href'), "Beitrag Teilen", "width=650,height=450,resizable=yes");
         fenster.focus();
         // Normale Link-Click-Aktion unterbinden
        event.preventDefault();
    })

Likes und Shares Laden

Nun können die Likes und Shares asynchron geladen werden. Dies geschieht aus dem Grund, damit keine Probleme auftauchen, falls hier mal etwas hakt oder hängt. Das Script kann im Hintergrund arbeiten, ohne die Funktion im Frontend zu beeinträchtigen.

$.ajax({
data: "url="+window.location,
data : "url="+ encodeURIComponent('http://www.coding-pioneers.com/'), type : 'POST', dataType : 'json', success : function(data) { // Alle Interaktionen setzen und Sichtbarkeit ändern. if (data.all == 0) { $('.share .share_counter').text('Bisher gibt es keine Interaktionen mit dem Beitrag - Teile ihn doch!'); } else { $('.share .share_counter').prepend(data.all + ' '); }
$('.share .share_counter').fadeIn(); // Facebook Interaktionen if (data.facebook != 0) { $('.share .btn-facebook .text').text(data.facebook + (data.facebook == 1 ? ' like' : ' likes')); }
// Twitter Interaktionen if (data.twitter != 0) { $('.share .btn-twitter .text').text(data.twitter + (data.twitter == 1 ? ' tweet' : ' tweets')); }
// Google Interaktionen if (data.google != 0) { $('.share .btn-google .text').text(data.google); } // Xing Interaktionen if (data.xing != 0) { $('.share .btn-xing .text').text(data.xing + (data.xing == 1 ? ' share': ' shares')); } }, error : function(error, msg) { // TODO ggf. Error-Reporting } });

Im Hintergrund übergibt eine JSON-Datei Daten wie die folgenden:

{
  "all": 6,
  "facebook": 1,
  "google":4,
  "twitter": 1,
  "xing": 0,
  "url": "http://www.coding-pioneers.com/"
}


Im Hintergrund sitzt der PHP-Contoller für dieses JSON-Datei:

$url = "http://www.coding-pioneers.com/";
if(isset($_POST['url'])) 
    $url = $_POST['url'];
function twitter($url='') { $json_string = file_get_contents('http://urls.api.twitter.com/1/urls/count.json?url='.$url); $json=json_decode($json_string,true); if($json['count']) return intval($json['count']); return 0; }
function google($url='') { // CURL initiieren & Parameter Setzen $ch=curl_init(); curl_setopt($ch,CURLOPT_URL,'https://clients6.google.com/rpc'); curl_setopt($ch,CURLOPT_POST,true); curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false); curl_setopt($ch,CURLOPT_POSTFIELDS, '[{"method":"pos.plusones.get","id":"p","params":{"nolog":true,"id":"'.rawurldecode($url).'","source":"widget","userId":"@viewer","groupId":"@self"},"jsonrpc":"2.0","key":"p","apiVersion":"v1"}]');
curl_setopt($ch,CURLOPT_RETURNTRANSFER,true); curl_setopt($ch,CURLOPT_HTTPHEADER,array('Content-type: application/json')); // CURL Resultate in String schreiben und schließen $curl_results = curl_exec($ch); curl_close($ch);
// JSON Parsen $json = json_decode($curl_results,true);
// Rückgabe vorbereiten if($json[0]['result']['metadata']['globalCounts']['count']) return intval($json[0]['result']['metadata']['globalCounts']['count']);
return 0; }
function facebook($url='') { // Auslesen über Facebook Graph $source='http://graph.facebook.com/?id='.$url; $result=json_decode(file_get_contents($source));
// Rückgabe vorbereiten if($result->shares) return intval($result->shares);
return 0; }

function xing($url='') { // CURL initiieren & Parameter Setzen $ch = curl_init(); curl_setopt($ch,CURLOPT_URL, 'https://www.xing-share.com/spi/shares/statistics'); curl_setopt($ch,CURLOPT_POST, 1); curl_setopt($ch,CURLOPT_POSTFIELDS, 'url='.$url); curl_setopt($ch,CURLOPT_RETURNTRANSFER, true);
// CURL Resultate in String schreiben und schließen $curl_results = curl_exec($ch); curl_close($ch);
// JSON Parsen $json = json_decode($curl_results,true);
// Rückgabe vorbereiten if($json['share_counter']) return intval($json['share_counter']);
return 0; }
// Einzelne Interaktionen $interaktionen['twitter'] = twitter($url); $interaktionen['google'] = google($url); $interaktionen['facebook'] = facebook($url); $interaktionen['xing'] = xing($url);
// Summe der Interaktionen $interaktionen['all'] = array_sum($interaktionen);

Fazit

Die Share-Buttons werden deutlich schneller geladen, haben eine deutlich angenehmere Handhabung, passen nun auch ins Bild der Webseite und die Werte der Seite, die durch das Script gewonnen werden, können so auch intern gespeichert werden und sind schneller und vor allem einfacher auswertbar.

Links

Demo der Buttons

Projekt auf Github

Website-Tuning Stage 3: Eine Zusammenfassung

Wie in dem ersten und zweiten Teil der Blogreihe erläutert, kommt es auf optimale, komprimierte und nötige Inhalte an. Viele Ressourcen werden daher nun asynchron geladen, sind komprimiert und zu größeren Teilen minifiziert. Um nun die letzten Prozente herauszukitzeln, haben wir Folgendes getan:

  • HTML minifizieren
  • CSS minifizieren
  • Bilder optimieren
  • SVG komprimieren
  • Google Maps entfernen
  • Webfonts und andere Bibliotheken selber hosten

HTML-Komprimieren und optimieren

Um das HTML zu minifizieren, werden im weitesten Sinne Whitespaces entfernt. Also Zeichen, die während der Entwicklung für die Struktur nötig sind bzw. ungemein helfen. Dem Browser ist es hinterher jedoch weitestgehend egal, wie viele Zeilenumbrüche im Quelltext sind oder wie strukturiert der Quelltext durch die IDE der Wahl eingerückt wurde (durch Tabstops oder mehrere Leerzeichen). Aufgrund dessen werden diese Whitespaces mithilfe eines kleinen Snippets im MODX vor der Ausgabe entfernt:

Des Weiteren wird bei uns zumeist der Quelltext mittels Kommentaren beschrieben, um diesen zu späteren Zeitpunkten auch noch gut verstehen zu können (Dokumentation). Diese Dokumentation ist für den live-Betrieb der Seite nicht erforderlich und wurde ebenso aus dem Quelltext entfernt.

So konnten noch einmal 6 von 19 KB und somit 31% gespart werden.

Weitere Ressurcen optimieren

Das Logo wird als SVG-Grafik eingebunden. Diese ist im weitesten Sinne eine XML-Datei, welche ebenso minifizierbar und komprimierbar ist. Somit wurden die Daten mit dem MIME-Typ „svg+xml/text“ zur nginx-Konfiguration hinzugefügt und die Datei minifiziert.

Google Maps wurde aus der Startseite entfernt. Grund hierfür sind die ca. 45 Requests des Browsers, bis die Seite tatsächlich geladen ist. Das führt dazu, dass einige wichtige Ressourcen parallel mit der Karte geladen werden und sich die Bandbreite teilen müssen und daher langsamer geladen werden. Die Karte braucht durchschnittlich 3-5 Sekunden bei einer guten Internetverbindung, bis keine weiteren Ressourcen mehr nachgeladen werden. Subjektiv betrachtet reagiert in der Zeit der Browser marginal träger, was vermutlich mit der Leistungsfähigkeit des Endgerätes einhergeht. Aufgrund des späten Ladens des CSS gibt es zudem noch ein Darstellungsproblem beim erstmaligen Laden der Seite mit Browsern mit der Webkit-Engine (nur eine halbe Karte wird angezeigt). Netter Nebeneffekt: Die Datenkrake Google bleibt den Besuchern zunächst erspart.

Bilder optimieren

Auf der Startseite von Coding-Pioneers wird ein größeres Bild (Keyvisual) genutzt. Dieses war in der ursprünglichen Größe knapp 1,6 MB groß. In einer kleineren Größe (Breite: 1900 Pixel) hatte es noch 450 KB und macht damit noch rund 50% der Seitengröße (Gesamt: 695 KB) aus. Der Webdienst compressor.io verspricht, Bilder um bis zu 90% zu verkleinern und das ohne Qualitätsverluste. Zu verlieren gab es also nicht viel, wenngleich 90% Verkleinerung nicht erwartet wurden. So konnten am Ende annähernd 100 KB gespart werden (446 KB reduziert auf 345 KB also eine Ersparnis von rund 23%), was also zu einer Gesamtersparnis von etwas über 10% führte.

Was wurde denn nun gespart?

Angefangen haben wir mit einem Prototypen, der in Summe 2,2 MB also grob 2200 KB groß war. Es wurden 70 Ressourcen geladen (zum größeren Teil asynchron durch Google Maps) und das Ereignis „ready“ des DOM wurde nach durchschnittlich 1650 ms ausgelöst.

Durch die Komprimierung müssen von den 930 KB nur 695 KB übertragen werden, das entspricht einer Einsparung von 25%.


Durch das Minifizieren von:

  • HTML: 19 auf 13 KB (31% Ersparnis), keine Ressourceneinsparung
  • CSS: 196 auf 88 KB (55% Ersparnis), durch das Zusammenfassen wurden zwei Dateien eingespart, die weniger geladen werden müssen. Hier konnte auch relativ viel eingespart werden, da die Bibliothek des Bootstrap vom Umfang reduziert werden konnte.
  • JavaScript: 100 KB auf 140 KB, da noch weitere Skripte gebraucht wurden, um andere Möglichkeiten zu eröffnen, dafür wurden zwei Requests gespart. Die Minifizierungsrate fällt hier leider nicht so hoch aus, da die eingebundenen Bibliotheken wie jQuery bereits maximal minifiziert sind.

  • Bilderkomprimierung: Mithilfe von compressor.io konnten 140 KB gespart werden also einer Gesamtersparnis von etwas über 15%.

In Summe haben wir so von den ursprünglichen 2100 KB gute 1400 KB in der Übertragung sparen können. Durch die Optimierung werden nicht mehr 68 Ressourcen geladen, sondern nur noch 20. Das DOM-Ereignis „Content Loaded“ wird nach 240-400ms vom Browser ausgelöst. Ab dem Moment werden die Daten beim Client gerendert und dargestellt. Darauf folgt dann das Ereignis „Ready“ nach durchschnittlich 1,5 Sekunden. Nun werden Funktionen aufgerufen, wie die jQuery-Funktion „ready“ und damit die letzten Operationen ausgeführt.

Fazit: Performance matters

Was sollten Sie also tun, damit die Seite so schnell wie möglich geladen wird? Hier eine kommentierte Liste zum Abarbeiten:

  1. Serverperformance: Suchen Sie sich einen guten Hoster und Webspace mit SSDs, so können Webseiten spürbar schneller bereitgestellt werden. Ein Webspace-Paket für 0,49 Euro / Monat und 2000 anderen Webseiten auf dem gleichen Server helfen nur bedingt. Gerade als Unternehmen spart man hier an der falschen Stelle!
  2. Optimieren Sie Ihre Bilder: Hier steckt mit das meiste Potenzial, um die Seitengröße schnell auf ein sinnvolles Maß zu bringen (Nur weil heutzutage jedes Smartphone kaum mehr Bilder von unter 4 MB erzeugt, müssen diese nicht direkt so auf die Webseite)
  3. Reduzieren Sie vor der Ausgabe Ihren CSS-Code: Zeilenumbrüche und Einrückungen strukturieren den Code zwar für Sie optimal und Kommentare noch einmal ungemein, aber dem Client (Browser) ist das zumeist vollkommen egal.
  4. Gleiches gilt für Ihren HTML-Code: So lassen sich schnell mal ein paar KB sparen.
  5. Für JavaScript gilt grundsätzlich das gleiche: Hier sind Optimierungen jedoch nicht ganz so trivial.
  6. Schalten Sie die Komprimierung (gzip/mod_deflate) ein: Ihre Webseite wird ca. 30% schneller geladen!
  7. Reduzieren Sie die Anzahl der Dateien bzw. fassen Sie Dateien zusammen, die geladen werden: Jede Datei, die gespart wird, spart einen HTTP-Header und blockiert damit keine anderen Ressourcen. Besonders CSS- und JavaScript-Dateien lassen sich gut zusammenfassen. Auch Bilder lassen sich in sog. Sprites zusammenfassen.
  8. Vermeiden Sie verschiedene Dateiquellen und laden Sie möglichst alles von einem Host. Auch wenn man Webfonts vom Anbieter A, jQuery vom CDN B und andere Bibliotheken von Anbieter C einbindet, sorgt das dafür, dass im Worst-Case drei DNS-Anfragen vor dem vermeidlich schnelleren Laden getätigt werden. Das blockiert den Browser kurzfristig und erhöht zudem die Anzahl der Fehlerquellen.

Wofür das Ganze? Sind wir schon fertig?

Die Seite wird nun insgesamt spürbar schneller geladen, was vor allem den mobilen Nutzern zugute kommt. Google hat hier für die Analyse das Produkt „PageSpeed Insights“ bereitgestellt. Hier räumen wir mit der aktuellen Seite 100 von 100 möglichen Punkten im Desktop-Bereich ab PageSpeed Insights von coding-pioneers.com

An einigen Ecken hakt es noch und an anderen Ecken liegt noch einiges an Potential. Hier wird es azyklisch immer mal wieder kleine Ergänzungen geben und wir werden diese mit Code-Snippets für Sie zur Verfügung stellen! Sie haben Fragen, Anmerkungen oder Wünsche – Wir freuen uns über Kommentare!

Links

Website-Tuning Stage 2: JS zusammenfassen & komprimieren

Im WWW ist sie kaum noch wegzudenken: Die Skriptsprache JavaScript. Sie dient unter anderem zur Dynamisierung der Inhalte einer Website. Der JS-Quellcode wird im HTML zwischen den script-Tags eingebunden oder dort mittels Attribut aus einer externen Datei geladen:

<script src="script.js"></script>

Wie bereits im letzten Teil der Serie erklärt wurde, ist es wichtig, dass so wenig Dateien wie möglich eingeladen werden. Das gilt auch für den eingebundenen JavaScript-Code. Die Ziele sind folgende:

  • Skriptdateien zusammenfassen
  • Quellcode minifizieren

Skriptdateien zusammenfassen

Auf einer Website können mehrere Skript-Dateien eingebunden werden. Wird eine Website in einem Web-Browser aufgerufen, läd dieser in der Regel 6 Dateien gleichzeitig. Dabei werden neben dem Skript auch Bilder, CSS-Dateien und weitere Elemente der Seite geladen. Deswegen ist es sinnvoll, die Anzahl der eingebundenen Dateien möglichst gering zu halten. Dies kann durch das Zusammenfassen aller erforderlichen Skript-Dateien zu einer Datei umgesetzt werden.

Quellcode minifizieren

Das weitere Vorgehen besteht in der Komprimierung der zusammengefassten Skript-Datei. Quellcode enthält oft für den Interpreter unwichtige Zeichen wie Zeilenumbrüche, Tabstopps und Kommentare. Diese Zeichen dienen nur dem Verständnis sowie der Förderung der Lesbarkeit und können daher restlos aus dem Quellcode entfernt werden. Durch diese Operation lässt sich die Größe der Skript-Datei um ein Vielfaches verkleinern, wodurch die Ladezeit der Datei verringert wird.

Folgende Elemente können restlos entfernt werden:

  • Zeilenumbrüche
  • Tabstops
  • Kommentare
  • Zeilenumbrüche
  • Aufeinander folgende Leerzeichen

MODX Snippet

Durch das folgende MODX-Snippet „minimize-js“ kann die Performance beim Laden das JavaScripts mit den zuvor beschriebenen Operation simpel verbessert werden. Der Aufruf des Snippets erfolgt durch [[minimize_js? ]]. Durch das Snippet werden die übergebenen Dateien zusammen gefasst und komprimiert. Da es sich um eine simple Komprimierung handelt, führen einzeilige If-Abfragen, welche einen Zeilenumbruch enthalten, zu einer fehlerhaften Ausgabe.

Parameter

NameBeschreibung
srcFilesPfade zu den JavaScript-Dateien, welche zusammengefasst und komprimiert werden sollen. Pfade werden durch ein Komma getrennt.

Quellcode des MODX-Snippets

<?php<br>
<br>
$srcFiles = $modx->getOption('srcFiles', $scriptProperties);<br><br>

/* Leerzeichen entfernen */<br>
$srcFiles = str_replace(" ", "", $srcFiles);<br><br>

/* Parameter aufsplitten */<br>
$params = explode(",",$srcFiles);<br><br>

$output = "";<br><br>

/* Source-Dateien optimieren */<br>
foreach($params as $file)<br>
{<br><br>

  /*Dateiinhalt auslesen */<br>
  $string = file_get_contents($file);<br><br>

  /* Einzeile Kommentare entfernen */<br>
  $string = preg_replace("/[^:](\/\/.*)/", "\n", $string);<br><br>

  /* Mehrzeilige Kommentare entfernen */<br>
  $string = preg_replace("/(\/\*.*\*\/)/s", "\n", $string);<br><br>

  /* carriage returns durch Zeilenumbruch ersetzen */<br>
  $string = str_replace("\r", "\n", $string);<br><br>

  /* tabs durch Leerzeichen ersetzen */<br>
  $string = str_replace("\t", "\n", $string);<br><br>

  /* Mehrere Zeilenumbrueche durch einen ersetzen */<br>
  $string = preg_replace("/\n+/", "\n", $string);<br><br>

  /* Zeilenumbrueche an schließenden Klammern durch Semikolons ersetzen */<br>
  $string = preg_replace("/[)]\n/", ");", $string);<br><br>

  /* Entfernt das Semikolon an If-Abfragen und Schleifen */<br>
  $string = str_replace(");{", "){", $string);<br><br>

  /* Entfernt das Semikolon am Punkt-Operator */ <br>
  $string = str_replace(");.", ").", $string);<br><br>

  /* Entfernt das Semikolon an zwei aufeinander folgenden runden Klammern*/<br>
  $string =preg_replace("/[);]\s+[);]/", ")", $string);<br><br>

  /* Restliche Zeilenumbrüche entfernen*/<br>
  $string = preg_replace("/\n/", "", $string);<br><br>

  /* Mehrere Leerzeichen durch ein Leerzeichen ersetzen */<br>
  $string = preg_replace("/\s+/", " ", $string);<br><br>


  $output = $output.$string;<br>
}<br>
<br>
return $output;<br>
?>

Verwendung

Nachdem mit dem zuvor beschriebenen Quellcode das MODX-Snippet erstellt wurde, muss dieses in die Website eingebunden werden. Dazu wird eine neue Ressource vom Content-Type „javascript“ erzeugt und das Snippet mit

[[minimize_js? &srcFiles=`js/script1.js,js/script2.js,js/script3.js`]]

eingebunden. Zu beachten ist, dass der Aufruf des Snippets ohne ein Ausrufungszeichen nach der zweiten öffnenden eckigen Klammer erfolgt, damit das Snippet gecacht wird. Durch das Cachen des Snippets wird zusätzliche Ladezeit gespart, da die Datei nicht neu geladen werden muss.

Die zuvor erstellte Ressource wird im Footer durch

<script src="ressourcen-name.js"></script>

Fazit

Durch die Verwendung des MODX-Snippet konnten wir die Größe unserer JS-Datei um 60% reduzieren. Hier bewegen wir uns ebenfalls im KB-Bereich. Dank moderner Datenübertragungstechniken spielt das Einsparen von KBs in der heutigen Zeit kaum noch eine Rolle. Aber auch hier gilt: „Serverentlastung bei Lastzeiten“ und „VDSL, Glasfaser und LTE sind nicht immer verfügbar“.

Bei dieser Methode der Komprimierung handelt es sich um ein simples Verfahren, welches eine Alternative zu externen Programmen, wie zum Beispiel dem Closure Compiler von Google, liefert. Durch das MODX-Snippet bleibt die gesamte Kontrolle bei dem Programmierer der Website und der Quellcode wird nicht an eine externe Schnittstelle gesendet.

Website-Tuning Stage 1: Code validieren und optimieren

Das WWW – wie wir es heute kennen – hat eine gewisse Entwicklung hinter sich. Durch diese ist letztlich auch HTML bzw. HTML5 entstanden, da es vorher keine Standards für die strukturierte Übertragung von digitalen Informationen zwischen mehreren Personen gab.

Zur Historie von HTML: Die Hypertext Markup Language gehört zur Klasse der sog. Auszeichnungssprachen, die einen Text semantisch strukturiert und es erstmals Ende 1992 ermöglichte Informationen spezifiziert über Ländergrenzen hinweg zu übertragen. Heutzutage wird HTML vom W3C und der WHATWG weiterentwickelt. Die derzeitige aktuellste Spezifikation ist HTML5, die bereits von den meisten Webbrowsern unterstützt wird.

Wenn nun entsprechend dieser Spezifikation der Quellcode geschrieben wird, so besteht auch eine größere Chance, dass dieser dann auf allen Endgeräten gleichartig interpretiert und angezeigt wird.

HTML5 validieren

Damit der Quellcode einer Webseite entsprechend der Spezifikation des W3C geschrieben wird, bzw. das Ergebnis sich prüfen lässt, gibt es vom W3C einen sog. Validatior. Werden hier Fehler oder Warnungen ausgegeben, so können diese korrigiert werden. Ein bekannter Validator ist unter folgender Domain zu finden:

html5.validator.nu

CSS validieren

Weiter verhält es sich mit dem CSS genauso wie mit dem HTML, hier wird auch ein Validator von W3C bereitgestellt:

jigsaw.w3.org/css-validator

Es fällt auf, dass hier etliche Fehler gefunden werden und der Quellcode angeblich alles aber eben nicht valide ist. Das liegt daran, dass CSS3 noch nicht spezifiziert ist (und damit kein Standard, der sich prüfen ließe) und bisher nur ein Entwurf ist, der permanent erweitert wird und dann durch die Browser-Engines implementiert wird. Dadurch gibt es auch die verschiedenen Browser-Präfixe (wie bspw. „-webkit“).

Nichtsdestotrotz lassen sich so einige Fehler im Stylesheet erkennen und bereinigen.

HTML5 und CSS optimieren

Damit das CSS und HTML so schnell wie möglich angezeigt werden, ist es wichtig, dass dieser Quellcode so schnell wie möglich geladen wird. Daraus folgt, dass zum einen der HTML und CSS-Code immer so klein wie möglich sein sollten und zum zweiten, dass auch nur das übertragen wird, was auch wirklich gebraucht wird.


Folgendes ist empfehlenswert:

  • Kommentare Entfernen
  • Kommentare aus Scripts und Styles entfernen
  • Entfernen von CDATA-Sektionen von Skripten und Styles
  • Überflüssige Leerzeichen und Zeilenumbrüche entfernen
  • Entfernen von leeren Attributen (class=„“)
  • Entfernen von leeren Elementen
  • URLs relativ angeben (URLs minifizieren)

Texte per HTTP-Kompression verkleinern

HTTP-Kompression, die von Servern und Webbrowsern unterstützt wird, dient der Verkürzung der Übertragungsgeschwindigkeit und der Optimierung der Bandbreitenausnutzung.

Komprimierbare Ressourcen (wie Textdateien also vor allem HTML, CSS und Javascript) auf einer Webseite, die mittels HTTP-Komprimierung bereitgestellt werden, sorgen dafür, dass sich bis zu 90% des benötigten Datenvolumens bei der Übertragung einsparen lassen. Viele Webserver können Dateien vor dem Senden mittels gzip komprimieren. Dies geschieht durch Aufrufen eines Drittanbietermoduls oder mithilfe integrierter Routinen. Dadurch können für das Rendern Ihrer Website erforderliche Ressourcen signifikant schneller heruntergeladen werden.

Bei anderen Ressourcen wie z.B. JPEG-Bildern lohnt diese Vorgehensweise nicht, da das Bild selber schon komprimiert ist.

HTTP-Kompression (gzip) im nginx-Webserver aktivieren

Aus allgemeinen Performancegründen arbeiten wir mit dem Webserver nginx. Dieser liefert die statischen Dateien deutlich schneller als ein Apache Webserver aus, sodass dieser hierhingehend konfiguriert werden muss. Die folgende Konfiguration beinhaltet die gesamte nginx-Konfiguration für das MODX-CMS:


location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg)$ {<br>
    expires 30d;<br>
    add_header Pragma public;<br>
    add_header Cache-Control "public, must-revalidate, proxy-revalidate";<br>
    try_files $uri = @fallback;<br>
<br>
    if (!-e $request_filename) {<br>
        rewrite ^/(.*)$ /index.php?q=$1 last;<br>
    }<br>
}<br>
<br>
gzip on;<br>
gzip_proxied any;<br>
gzip_types  application/javascript application/json application/xml application/xml+rss application/x-javascript text/css text/javascript text/plain text/xml;<br>
gzip_vary on;

Fazit

Alleine durch diese kleinen Optimierungen konnte der Textanteil der übertragenen Daten von ca. 250 kB auf rund 70 kB, also um über 70% gesenkt werden. Diese läppischen 180 kB sind zwar in Zeiten von VDSL, Glasfaser und LTE kaum der Rede wert, entlasten aber dennoch gerade in Lastzeiten den Server enorm und auch einen geneigten Interessenten, der eben doch nur über EDGE oder GPRS mit dem Internet verbunden ist.