Archiv für den Autor: Heiko Mamerow

Über Heiko Mamerow

Ich bin freier Front-end Entwickler aus Berlin und habe mich auf die Erstellung von Internetseiten mit WordPress spezialisiert.

WordCamp Colgone 2015 – Meine Abrechnung ;-)

Ein chronologischer Ablauf (m)eines wunderbaren Wochenendes beim WordCamp Cologne MMXV in Wort und Bild:

Banner_768_90

Freitag, 05.06.15

5:00 Uhr – Biiiep! Biiiep! Biiiep!

Ok, mein Start in das #wccgn-Wochenende war nicht ganz soooo wunderbar: Es begann mit dem unsaften Weckerruf um 5:00 Uhr. Der mich gnadenlos aus dem viel zu kurzen Schlaf riss. Rasieren, Duschen und der erste Kaffee. Noch schnell ein paar Brötchen für unterwegs geschmiert, Ladekabel einpacken. An alles gedacht? Ok, dann kann es ja los gehen. Auf zum Bahnhof. Der ICE nach Köln wartet nicht.

tschuess-berlin

Tschüss Berlin!

Der Morgen war freundlich, hell und klar. Als ich im ICE losfuhr, hatte ich großes Glück: viel Platz, keine lärmende Schulklasse oder Lauttelefonierer im Abteil. Um mich herum lauter verschlafene Gestalten. Die beste Grundlage, um entspannt zu frühstücken und an der Präsentation zu feilen.

11:09 Uhr: Warmup am Kölner Hauptbahnhof

koeln-hbf

Hallo Köln!

Knapp 4,5 Stunden später kamen wir pünktlich in Köln an. Und es gab einen sehr warmen Empfang am Bahnsteig: Fast 32°C im Schatten. So lässt es sich aushalten in Köln. An ein obligatorisches Kölner-Dom-Foto war da allerdings nicht zu denken. Nur schnell weg hier. Ab zum Hotel.

Im Hotel war es allerdings auch nicht besser. Die Sonne knallte voll auf das unklimatisierte Zimmer. Es war sehr mollig. Aber was mich wirklich zum Schwitzen brachte, waren die „Anrufe in Abwesenheit“ auf meinem Telefon. Schnell war klar, den Nachmittag in der Uni beim #wccgn und die Warmup-Party konnte ich vergessen. Ich musste noch etwas arbeiten…. ;-(

Außerdem hatte ich ja mein Präsentation noch nicht fertig. Während der Zugfahrt hatte ich nämlich noch ein paar – wie ich fand – sehr gute Einfälle, die Umgesetzt sein wollten. Und so saß ich dann noch nach getaner Arbeit die halbe Nacht und habe die Präsentation für den Vortrag umgeschrieben. Gegen 4:00 Uhr früh war Feierabend. Ich konnte nicht mehr…. zzzzzzzzzz

Samstag, 06.06.15

7:00 Uhr: Biiiep! Biiiep! Biiiep!

Oooch neeeee, nicht schon wieder! Dieses Horrorgeräusch vom Wecker hatte ich in den letzten Tagen leider schon so oft hören müssen. Na gut, nützt nichts, muss Aufstehen, kein Pardon. Irgendwie geduscht und raus auf die Straße. Keine Ahnung wohin. Google Maps ist schon eine coole Erfindung. ;-)

7:40 Uhr – Ups, falscher Planet

Die Kölner scheinen den Tag lieber etwas später zu starten. Frühstück gab es im Hotel nämlich erst ab 8:00 Uhr. Da sollte ich aber schon in der Uni beim #wccgn sein. Also erstmal mit knurrenden Magen und Kaffe-Entzug in die falsche Straßenbahn eingestiegen.

Es dauerte eine Ewigkeit, bis ich meinen kleinen Fahrfehler bemerkte. Na super! Die nächste Bahn in die richtige Richtung ließ dann noch ewig auf sich warten. Damit war klar, ich komme zu spät zum Helfer-Meeting. ;-(

8 Uhr-irgendwas: Na endlich

Irgendwann war ich dann endlich da, wo ich hingehörte. Ganz aufgeregt und gespannt und auch beschämt wegen meiner Verspätung. Aber das hat niemanden interessiert. Die Orga-Leute waren natürlich schon viel eher da und hatten die wichtigsten Vorbereitungen vor Ort längst abgeschlossen. Sie hatten alles im Griff. Man merkte sofort, dass sie das WordCamp lange und gründlich vorbereitet hatten. Ihre Gelassenheit und Freundlichkeit sprang auf mich über und gab mir das schöne Gefühl, Willkommen und dabei zu sein.

willkommen

Es wird voller und voller

Nach und nach füllte sich langsam das Uni-Gebäude mit den 346 Teilnehmerinnen und Teilnehmern. Viele kennen sich schon seit Jahren ganz gut und die Atmosphäre war entsprechend sehr familiär und ungezwungen. Die Leute, die man noch nicht kannte, konnte man ja jetzt kennen lernen. Also auf ins Gedränge. Ich bin sonst eigentlich ein typischer Mecklenburger – etwas scheu und zurückhaltend. Aber hier beim Camp war ich wohl in der Beziehung eher wie ein Südländer  und wurde auch südländisch – also offen und herzlich – empfangen.

10:00 Uhr: Jetzt geht es endlich los

00sleepy

00Sleepy – Der Schrittmacher :-)

Die Begrüßung machte Thomas Brühl (aka 00sleepy). Er war der Lead-Organiser des WordCamps und hatte sage und schreibe 44.444 Schritte für die Community zurückgelegt! DU ROCKST!

keynote

Keynote: Was war, was ist, was wird.

Anschließend gab es die Keynote mit Pascal Birchler. Huch auf englisch? Na warum auch nicht. Es war ja schließlich auch internationales Publikum da.

Quo vadis?

Es gab (fast) immer vier parallele Vorträge zur Auswahl. Und damit hatte man die Qual der Wahl, wohin man denn nun jeweils geht. Das Angebot an Themen und Sprecher war sehr umfangreich. Von hause aus interessieren mich natürlich eher die technischen Themen. 

Durch meinen Job als freiwilliger Helfer hatte ich das Glück, dass ich – wenn ich Dienst hatte – keine Wahl hatte, sondern immer in einer bestimmten Sitzung gehen musste. Das stellte sich für mich als willkommene Horizonterweiterung raus. So fand ich mich bei Vorträgen, die ich eher nicht gewählt hätte, die mich aber – vielleicht gerade deshalb? – sehr inspirierten.

Themenauswahl

Aus über 90 Vorschlägen für Vorträge wurden am 33 ausgewählt. Damit war das WordCamp randvoll gefüllt. Die Auswahl der Vorträge war bemerkenswert: Jedes Orga-Mitglied hat nach einem Punktesystem jeden Vortrag bewertet. Am Ende sind dann die Vorträge mit der besten Bewertung angenommen worden. Berücksichtigt wurde auch, dass alle Themenbereiche abgedeckt waren und das Verhältnis der englischen Vorträge.

Helfer

Neben dem Orga-Team – was die eigentlichen Macher des WordCamps waren – gab es auch noch die Helfer vor Ort. Viele fleißigen Hände, die ebenfalls zum Gelingen der Varanstaltung beigetragen haben. Ich selbst hatte mich auch als Helfer gemeldet. So eine Veranstaltung macht sich schließlich nicht von allen. Da wird jede Hand gebraucht. Ehrensache!

Mein Job war die Sprecherbetreuung. Das wichtigste daran ist: den Sprecherinnen und Sprechern alles „Drumherum“ bei Ihrem Vortrag abzunehmen: Man führt sie in den richtigen Saal, sorgt dafür, dass frisches Wasser da ist, klemmt das Mikro an und versucht, die Aufregung zu vertreiben. Während der Sitzung passt man dann auf, dass alles ok ist und hält am Ende die Zeit-Kärtchen hoch, damit der Sprecher weiß, wie viel Minuten er noch bis zum Vortragsende hat.

11:00 Uhr: Hans-Helge Bürger – WordPress REST API

hans-helge-restapi

WP REST API mit Hans-Helge

Hans-Helge hat uns erklärt, was die neue neue WP REST API ist und was man tolles damit anfangen kann. Für mich einmal mehr der Impuls, mich endlich damit auseinanderzusetzen.

12:00 Uhr: Mittagspause und noch etwas mehr

Vor der Mittagspause hatte ich noch etwas Luft und wollte unbedingt noch schnell etwas an meiner Präsentation weiter arbeiten. (So ein Unsinn, wer fährt denn auf ein WordCamp um dort vor dem Computer zu hocken??? Mache ich bestimmt nicht mehr.) Ich hatte den PC noch nicht mal richtig aufgeklappt, da saß schon jemand neben mir: „Oh, stör ich dich?“ – Natürlich nicht Annette! :-)

Annette wollte sich nur bei mir bedanken für einen Vortrag über Grunt, den ich mal beim WP-Meetup in Potsdam gehalten hatte. WOW, da war ich platt! Und zum ersten Mal begannen meine Selbstzweifel ein klitzekleinwenig zu schrumpfen. Das hatte Annette einfach mal so hingekriegt. DAS IST GEMEINSCHAFT!

Wir hatten uns intensiv über WordPress und das Leben als Freelancer unterhalten. Das war ein sehr anregendes Gespräch. Ich war so gebannt, dass ich total meinen nächsten Helfer-Deinst vergessen hatte. Zerknirscht bin ich also viel zu spät zu Alex Reach gegangen, der sich mit um die Sprecher-Helfer kümmerte. Aber nicht einmal das war schlimm. Ein Ersatz für mich war längst problemlos gefunden. Aufatmen und noch eine Cola auf den Schreck.

14:00 Uhr: Frank Bültge – Der Customizer, ein Standard Control

frank-costumizer Natürlich lasse ich mir eine Session mit Frank Bültge nicht entgehen. Andererseits wollte ich mir auch gerne den Barrierefreiheit-Vortrag von Elisabeth Hölzl anschauen. – Nun, die Münze hat entschieden… :-)

Nach Franks Vortrag hatte ich das große Glück, Ellen Bauer und Manuel Esposito „in echt“ kennen zu lernen und Ihnen meine Bewunderung auszudrücken. Ich wünsche den beiden viel Glück und einen guten Start am anderen Ende der Welt!

15:30 Uhr: Kirsten Schelper – Buzzword Information Architecture

kirsten

Beste Präsi ever! :-)

Wie oft habe ich in Kirstens Vortrag wohlwissend mit dem Kopf genickt. Sie hat mal wieder den Nagel voll auf den Kopf getroffen: „Zusammenarbeit zwischen Kunde, Designer und Coder verläuft improvisiert bis chaotisch.“ – Autsch ja, manchmal… ;-)

Und nochwas: Wer 1a gestaltete und dramaturgisierte Präsentationen sehen will, der gehe in Kirstens Vorträge!!!

Und der ganze Rest….

Die letzten Vorträge konnte ich mir leider nicht mehr anschauen, ich musste wieder zurück ins Hotel – Die Arbeit…. Auch die Party habe ich sausen lassen. Denn meine Präsentation war noch nicht fertig überarbeitet. Der Abend wurde noch seeeeehr lang. Eigentlich sogar endlos. Gegen 2:00 Uhr war die Präsentation endlich fertig überarbeitet. Aber an Schlaf war vor Aufregung nicht zu denken.

Sonntag, 07.06.15

9:00 Uhr: Biiiep! Biiiep! Biiiep!

Den Wecker hätte ich mir diesmal sparen können. Ich war todmüde aber wach, kein Schlaf…

10:00 Uhr: Gekniffen :-/

Ausgerechnet bei dem Vortrag , auf den ich mich am meisten gefreut hatte, habe ich gekniffen und bin nicht rein gegangen.

Liebe Ellen, lieber Manuel das tut mir sehr leid. Wegen meines eigenen Vortrages, war ich so aufgeregt, dass ich nicht in Eure Sitzung gehen konnte. Statt dessen war ich draußen und habe Entspannungsübungen gemacht, um mich ein zu kriegen.

Das ich nicht der Einzige war, der sich auf die beiden gefreut hat, war ja wohl klar. Ich würde sagen, der Vortrag von Elmastudio war der Höhepunkt vom ganzen WordCamp.

11:00 Uhr: Ich bin dran

Dann kam die Stunde der Wahrheit. Mein erster Vortrag auf einem WordCamp. Das Herz steckte mir schon seit Tagen in der Hose und besonders in der letzten Nacht hatte ich nicht geschlafen. Mein Aufregung war endlos. Aber Moment, Ich bin doch Buddhist. Da müsste ich doch eigentlich meinen Geist unter Kontrolle haben. Ja, müsste… Aber in Wirklichkeit habe ich einmal mehr erfahren, wie sehr man leidet, wenn man seinen Geist nicht unter Kontrolle hat. Diese Erfahrung hat mir im Nachinein sehr großen Schwung gegeben, mich auf meinem spirituellen Weg noch mehr zu bemühen. Doch ich schweife ab, hier soll es ja um den Vortrag gehen.

An Details von meinen Vortrag kann ich mich allerdings kaum erinnern. Den Vortrag muss ich mir wohl später selber mal bei WordPress TV anschauen. Aber an eins kann ich mich noch sehr gut erinnern: an die Einleitung. Da hat mir nämlich ein alter Sprecher-Trick sehr geholfen: Lerne die Einleitung auswendig.

Mit der sicheren Einleitung konnte ich irgendwie meinen „Flow“ finden. Und habe halt die Dinge erzählt, die ich so über Web-Perfomance weiß. Die große Herausforderung war dabei, den Vortrag so zu halten, dass „Nicht-Techie“ etwas damit anfangen können. Vor allem Fachwörter galt es gut zu umschiffen.

Zwischendurch und ganz zum Schluß gab es auch noch jede Menge Fragen von den Zuhörern. Das nehme ich mal als ein gutes Zeichen. Die Leute waren sehr am Thema interessiert. Und weg gerannt ist niemand. :-)

Meine Präsentation habe ich bei Speakerdeck hoch geladen: https://speakerdeck.com/heikomamerow/das-kleine-1×1-der-web-performance

PS: Leider sind die Animationen in der PDF nicht aktiv.

12:00 Uhr: Der Rest…

Der Rest vom Sonntag und auch der Contributor Day am Montag wird hier auch noch nachgereicht. Versprochen!!! :-)

WordCamp Europe 2015 – Freiwilliger Helfer

Das WordCamp Europe findet dieses Jahr vom 26. – 28. Juni in Sevilla (Spanien) statt. ich werde dabei sein und dort tatkräftig zusammen mit vielen anderen freiwilligen Helfern zum Gelingen der größten WordPress-Konferenz beitragen.

wceu15_badge_volunteer-1

Ich bin sehr gespannt, was mich dort erwartet. Auf jeden Fall muss ich jetzt anfangen, ein paar Brocken Spanisch zu lernen. ;-)

WordCamp Cologne MMXV: Ich bin Community Sponsor

Bisher gibt es (erst) zwei drei schon fünf sogar sechs Communiy-Sponsoren beim WordCamp Cologne MMXV. Jawoll, ich bin einer davon. Und es werden hoffentlich noch viele – auch bei den großen Sponsoring-Paketen….

Banner_300_300

Klicke auf das Bild, um zu den Sponsoring-Paketen zu gelangen.

Ich bin sehr glücklich, dass ich endlich auch mal auf diese Weise der Open Source Community ein kleines bisschen zurück geben kann. Immerhin verdiene ich meine Brötchen mit einer super CMS-Software, für die ich nichts bezahlen muss. Danke an alle! :-)

WordPress-Websites von überflüssigem CSS-Code mit „UnCSS“ befreien

In diesem Tutorial möchte ich zeigen, wie man die CSS-Datei einer WordPress-Website verkleinert, indem man überflüssigen bzw. nicht genutzten CSS-Code findet und entfernt. Mit dieser Maßnahme kann man die Performance der Website verbessern.

Um Euch mal einen Geschmack zu geben, was eigentlich der Nutzen ist, habe ich eine Testseite mit WordPress angelegt und sie mit und ohne „gesäuberten“ CSS verglichen:

uncss-less-code

50% weniger Code beim WP-Theme „Twenty Fourteen“ durch UnCSS.

Die style.css vom aktuellen Standard-Theme Twenty Fourteen ist unkomprimiert 77,4 kB groß. Nach dem Entfernen vom überflüssigen CSS-Code hatte die bereinigte Datei nur 39,0 kB! Diese Zahlen sprechen für sich.

Wie immer möchte ich erstmal grundsätzlich das Thema erörtern und im zweiten Teil, dann konkrete die Lösung beschreiben.

Teil 1: Worum geht es – Grundlagen

Was ist überflüssiger CSS-Code?

Mit überflüssigem CSS-Code ist hier der Code im CSS gemeint, welcher nicht für die Beschreibung der Format-Eigenschaften im HTML benötigt wird. Man kann zwei Arten von überflüssigem CSS-Code unterscheiden:

A) Nicht verwendeter CSS-Code:
Das sind Style-Definitionen, für die es im HTML keine Verwendung gibt. Die schleichen sich z.B. durch Reset-Stylesheets ein. Bei Reset-Stylesheets werden für alle möglichen HTML-Elemente Style-Definitionen festgelegt. Wenn aber in der Website nicht alle HTML-Elemente zum Einsatz kommen, hat man unnötigen Ballast in der CSS-Datei.

B) Überschriebener CSS-Code
Das sind Style-Definitionen, für die es im HTML zwar eine Verwendung gibt, die aber von anderen Definitionen überschrieben werden.

Die hier vorgestellte Methode erkennt beide Arten und elemeniert sie.

Teil 2. Finden und Ersetzen von überflüssigem CSS-Code

Im Prinzip geht man wie folgt vor:

  1. Es wird eine Sitemap mit allen URLs der Website erstellt.
  2. UnCSS erfasst anhand der Sitemap die Seiten und holt sich darüber auch alle Stylesheets – sowohl inline Styles als auch externe CSS-Dateien.
  3. Außerdem erfasst UnCSS alle Selektoren aus dem HTML.
  4. Dann werden alle Selektoren mit den Stylesheets abgeglichen.
  5. Die Stylesheets, für die es Selektoren gibt, wandern in eine neu generierte CSS Datei.*

*Das Zusammenfügen von mehreren Stylesheets-Dateien zu einer einzigen hat übrigens den schönen Nebeneffekt, dass man dadurch die Anzahl der HTTP Requests verringert.

Praktische Durchführung

1. Sitemap Plugin installieren

Kopiere das Sitemap Plugin von Liam Gladdy in das Verzeichnis /wp-content/mu-plugins
Ja, richtig gelesen. Das Verzeichnis soll mu-plugins heißen. Was das ist, erfährst Du hier.

2. Grunt und Plugins installieren

Du brauchst:

Unter Ubuntu reicht für die Installation dieser Einzeiler:

sudo npm install grunt --save-dev && sudo npm install --save-dev load-grunt-tasks && sudo npm install --save-dev grunt-exec && sudo npm install --save-dev grunt-uncss

**Kleiner Einschub für alle, die noch keine Erfahrung mit Grunt haben: Ich werde beim Potsdamer WP-Meetup am 18. November eine Einführung in Grunt geben. Die wird es dann auch als Stream im Internet geben und entsprechende Dokumentation.

3. Gruntfile.js einrichten

Jetzt noch die Datei Gruntfile.js im Hauptverzeichnis des Projektes anlegen, den folgenden Code dort rein kopieren und die Verzeichnisse und Dateinamen anpassen:

// Wrapper - Nichts verändern!
module.exports = function(grunt) {
	'use strict';

	// Grunt Tasks
	grunt.initConfig({
		pkg: grunt.file.readJSON('package.json'),

		// Task für die Sitemap
		exec: {
			get_grunt_sitemap: {
				// Hier den Pfad zur Sitemap anpassen.
				command: 'curl --silent --output sitemap.json http://wohinauchimmer/wordpress/uncss/?show_sitemap'
			}
		},

		// Konfiguration von UnCSS
		uncss: {
			dist: {
				options: {
					//Hier ggfls. noch weitere Selektoren eintragen, die ignoriert werden sollen.
					ignore       : [/expanded/,/js/,/wp-/,/align/,/admin-bar/],
					// Hier den Link zur originalen CSS-Datei eintragen.
					stylesheets  : ['style-original.css'],
					// Hier die Links zu den CSS-Dateien eintragen, die generell ignoriert werden sollen.
					ignoreSheets : [/fonts.googleapis/],
					// Hier nichts verändern oder eintragen!
					urls         : []
				},
				files: {
					// Hier den gewünschten Pfad und Namen der erzeugten CSS-Datei eintragen.
					'style-uncss.css': ['**/*.php']
				}
			}
		}
	});

	// Hier werden die Plugins geladen. Nichts verändern!
	require('load-grunt-tasks')(grunt);

	// Hier werden die Tasks registriert. Nichts verändern!
	grunt.registerTask('load_sitemap_json', function() {
		var sitemap_urls = grunt.file.readJSON('./sitemap.json');
		grunt.config.set('uncss.dist.options.urls', sitemap_urls);
	});
	grunt.registerTask('uncss_style', [
		'exec:get_grunt_sitemap',
		'load_sitemap_json',
		'uncss:dist'
	]);
}

4. Grunt Task starten – UnCSS-isierte Datei erzeugen

Terminal öffnen, zum Projekt-Verzeichnis wechseln und den Grunt Task starten:
grunt uncss_style

grunt-uncss-terminal

Terminalausgabe des uncss-Task

Und …schwupp… haben wir eine „UnCSS-isierte“ CSS-Datei erzeugt, die wirklich nur die Styles enthält, die benötigt werden. Je nach Größe der Website kann das Generieren der uncss-Datei einige Zeit dauern. Es empfiehlt sich daher, diesen Task nicht mit watch bzw. Livereload zu verbinden.

Risiken und Nebenwirkungen

Mit UnCSS wird der IST-Zustand einer Seite ausgewertet. Dieser Zustand ändert sich sobald etwas am Theme oder am Inhalt geändert wird. Darum muss das Layout immer überprüft werden bzw. man sollte von Zeit zu Zeit den UnCSS-Task ausführen, damit neu hinzu gekommene Selektoren beachtet bzw. die Styles von weggefallenen Selektoren entfernt werden.

Es versteht sich, dass Ihr UnCSS sowieso erstmal bei einem Testprojekt ausprobiert. Außerdem solltt Ihr nach jedem uncss-Task gründlich prüfen, ob nicht vielleicht irgendwo zu viel Styles weggenommen wurden. UnCSS soll mit komplexen Selektoren nicht arbeiten.

Ich verwende UnCSS bei meinen neuen Themes und es kommt nur sehr selten vor, dass mal irgendwo ein Style zu viel fehlt. Das lässt sich dann aber sehr leicht mit der „ignore“-Option (siehe oben im Code) fixen. Einfach den betreffenden Selektor eintragen. Und den Task neu starten. Dann wird der Selektor nicht mehr entfernt.

Quellen und Dank

Ohne diese Entwickler und Tools wäre UnCSS für uns nicht möglich:

Das wichtigste Tool für uns ist UnCSS von Giacomo Martino. Damit werden die überflüssigen CSS-Codes gefunden und eleminiert.

Das wir UnCSS komfortabel in Grunt anwenden können, haben wir Addy Osmani mit seinem Grunt Task grunt-uncss zu verdanken.

Und last not least das WordPress-spezifische Know-how für diese Methode stammt aus dem Beitrag von Liam GladdyUsing UnCSS and grunt-uncss with WordPress Liam zeigt dort, wie man UnCSS für WordPress Websites anwendet. Und von ihm ist auch das Sitemap-Plugin, welches wir für den Grunt Task brauchen.

 

CSS-Trick: CSS asynchron laden

CSS asynchron laden ist ein kleines Schmankerl für fortgeschrittene Web-Performance-Enthusiasten, die bereits alles auf ihrer Website optimiert haben. Wenn Du schon die Bilder skaliert und web-optimiert, den Code komprimiert, minifiziert und kombiniert, alles gecached und auf ein CDN verteilt hast, dann – erst dann! – ist asynchrones CSS Dein neuer Spielplatz. Alle anderen müssen erstmal ihre Hausaufgaben machen… ;-)

css-synchron-asynchron-opt2
image-155992

Basiswissen

Rendering ist das, was der Browser macht, wenn er eine Website darstellt. Dazu braucht es Zeit. Je schneller der Render-Przess durchlaufen wird, desto schneller ist die Website. Aus verschiedenen Gründen muss das Rendering manchmal unterbrochen bzw. geblockt werden. Dieses Blockieren vermindert die Performance der Website.

CSS und Javascript blockieren das HTML-Rendering einer Website. Wenn der Browser das HTML-Dokument abarbeitet und an die Stelle gelangt, wo JS oder CSS eingeführt wird, unterbricht er das Rendern und arbeitet erstmal das Scrtipt oder den Stylesheet ab. Wenn das abgeschlossen ist, geht es mit dem HTML-Rendering weiter. In diesem Zeitraum passiert nichts im Browser. Der User muss warten und sieht so lange (meistens) nur eine leere weiße Seite.

Während man bei JS sehr einfach die Blockaden vermindern kann, ist das mit CSS nicht so einfach. Wie man Rendering mit JS optimiert erkläre ich hier nicht. Dazu gibt es genug Infos im Netz.

Wie man das Rendering verbessert.

Mit den folgenden Methoden kann man die Blockaden im HTML-Rendering beeinflussen, welche durch CSS verursacht werden:

  1. Inline CSS
    Hier wird der Code direkt in das HTML-Dokument eingebettet. Das Rendering wird zwar geblockt, aber die Zeit für das Anfordern und Herunterladen einer externen CSS-Datei entfällt.
  2. Später Aufruf
    CSS wird im HTML-Dokument vor dem </body> gelegt. Auch hier wird das Render-Blocken nicht vermieden. Aber es wird so nach hinten verlagert, dass die Website schon mal angezeigt wird, wenn auch noch nicht richtig gestylt..
  3. Später Nachladen
    Die CSS-Datei wird mittels Javascript später in das Dokument eingefügt, wenn das Rendern der Seite abgeschlossen ist oder zumindest bis zu einem Punkt gelangt ist, wo die Seite schon verwendbar ist.
  4. Asynchrones Laden
    Die CSS-Datei wird parallel zum Code geladen und ausgeführt. Hier wird das Rendering nicht geblockt.

In diesem Artikel beschäftige ich mich vorwiegend mit dem asynchronen Laden von CSS. Zur Optimierung des Rendering müssen alle Methoden eingesetzt werden.

Warum das HTML-Rendering wegen CSS geblockt wird

Das Rendering wird für CSS unterbrochen, weil Scripte oft Informationen vom CSS brauchen. Würde ein solches Script vor dem CSS geladen, würde es diese Informationen nicht erhalten und Fehler produzieren. Darum muss CSS – zumindest das für Scripte potentiell relevante CSS – immer vor den Scripten geladen werden! Dieses CSS nennt man auch kritisches CSS.

Kritisches und unkritisches CSS

Was ist kritisches CSS? Kritisches CSS sind die Styles, die man für den sichtbaren Bereich einer Website benötigt = Above the fold. Das ist der sichtbare Bereich im Browser, wenn eine Seite geladen wurde und man noch nicht gescrollt hat.

Wenn man CSS asynchron laden will, muss man also wissen, dass man grundsätzlich nur unkritisches CSS verwenden sollte. Unkritisches CSS sind die Styles, die für den nicht sichtbaren Bereich einer Website benötigt werden = Below the fold.

Regeln

Die Regeln sind klar. Das wichtigste woran man denken muss:

  1. Below the fold kann man asynchron laden.
  2. Above the fold muss man inline oder als externe Datei im Head aufrufen.

Woher zum Teufel kriege ich dieses kritische und unkritische CSS?

Das ist die eigentliche Herausforderung. Es gibt verschiedene Tools und Methoden, wie man sein CSS zerteilen kann. Als Lektüre dazu möchte ich auf einen Beitrag bei CSS-Tricks verweisen: Authoring Critical Above-the-Fold CSS. Hier beschreibt Gastautor Ben Edwards den Stand der Dinge bei der Umsetzung.

Workflow Ansätze

Aus meiner Sicht gibt zwei Ansätze für den Workflow:

  1. Man verwendet PageSpeed Module auf dem Server und überlässt dem „Prioritize Critical CSS„-Filter die Arbeit. Das ist mit Sicherheit die bquemste Lösung.
    Allerdings hat das Modul einen pragmatischen Hacken: Man benötigt Root-Rechte (sudo) für die Installation. Das ist leider bei meinen Kunden meistens nicht gegeben. Die meisten meiner Kunden betreiben Ihre Websites auf einfachen shared Webspaces. Sie haben keinen Root-Server. (Nicht mal ich habe das…)
  2. Integration eines CSS-Tools in die lokale Entwicklungs-Umgebung.
    Am praktikabelsten ist dabei für mich die Einbindung mit Grunt. z.B. Penthouse

Es gibt übrigens von Penthouse auch eine Online-Version. Aber damit kann man nur das kritische CSS einer Seite erstellen. Die obige Grunt-Version checkt dagegen die gesamte Website.

CSS asynchron laden

Von Scott Jehl gibt es ein sehr gutes Script, mit dem sich unrkitisches CSS sehr einfach einbinden lässt: loadCSS

LoadCSS macht dabei nichts anderes, als das die Medienabfrage (Media Query) zunächst auf einen unverfänglichen Wert zu setzen, der das Rendering nicht unterbricht – hier auf „nichts besonderes“:

<link rel="stylesheet" href="irgendwas.css" media="nichts besonderes">

Wenn das Rendering durch ist, schaltet das Script den Wert um – hier auf „all“:

<link rel="stylesheet" href="irgendwas.css" media="all">

Jetzt wird das Rendering wieder aufgenommen und das unkritsche CSS wird verwendet.

Für den Fall der Fälle, dass ein Browser mit JavaScript nicht klar kommt, sollte man als Fallback nicht vergessen, mit <noscript> das unkritische CSS-File nochmal vorzuhalten.

Schlussfolgerung

Die letzte Bastion des Rendering-Blockings ist endgültig gebrochen. Web-Performance-Optimierung wird damit noch komplexer und ich werde bei künftigen Projekten unkritisches CSS asynchron auslagern bzw. kritisches CSS inline einbauen.

Downloads

Lektüre

WordPress Meetup Potsdam: Un-Vortrag zu Performance

Am 24. Juni war wieder WordPress Meetup in Potsdam. Und ich hatte einen kleinen „Un-Vortrag“ zum Thema Performace gehalten. Dabei hatte ich versucht zu erklären, was eine Website schnell macht und wie man das mit WordPress hin bekommt.

tl;dr Die Slides gibt es bei GitHub

„Performance is a feature.“

google-performance-is-a-feature

Screenshot von Web Fundamentals

Meine Motivation für diesen Vortrag war/ist, das Thema Performance bei Entwicklern, Anwendern und v.a. Entscheidern anzubringen. Allgemein versteht und bejaht jeder die Nützlichkeit von performanten Websites. Aber mit der Umsetzung scheitert es dann zu oft in der Praxis. Das kenne ich aus eigenen Projekten zur genüge. Und selbst diese meine eigene Website hat noch Optimierungspotential. Naja, Schusters Kinder… ;-) Die Auftraggeber haben zwar einen Etat für einen Relaunch mit Kommunikation, Grafik und Programmierung. Aber Performance-Optimierung ist eher keine Position. Das wird immer irgendwie impliziert. Am Ende findet keine explizite Performance-Optimierung statt. Wenn sie nicht vorhanden ist, macht das auch nichts. Denn im Büro mit sattem DSL ist Performance eher kein Thema. Aber wehe, wenn man mal versucht irgendwo in einer „Mobilfunk-Wüste“ (oder einfach nur am nächsten Bahnhof) mit sehr wackeliger und dünner Internetverbindung eine 10MB große Website aufzurufen. Das wird eine schöne Übung in Geduld.

Warum performante Websites wichtig sind

Passender Weise hatte ich just ein paar Tage vor dem Vortrag ein einschlägiges Erlebnis zum Thema Performance gemacht: Auf der Suche nach einer Steuerberatung für mich hatte ich gegooglet. Und problemlos etliche Suchergebnisse mit Steuerberatungskanzleien aus dem Prenzlauer Berg erhalten. Die drei bestplatziertesten Ergebnisse hatte ich angeklickt.

625px-Grapevinesnail_01

Manche Websites sind lahm wie eine Schnecke :-) (Bildquelle: von Jürgen Schoner [GFDL oder CC-BY-SA-3.0], via Wikimedia Commons)

Leider war eine Seite davon so langsam beim Laden, dass ich sie – nach dem ich die anderen beiden Seiten kurz gecheckt hatte – ungelesen wieder geschlossen hatte. Diese Steuerberatung hatte – nur weil Ihre Website so lahm unperformant war – einen potentiellen Mandanten verloren. So spielt das Leben… Aber davon mal abgesehen, ist für mich natürlich der Erfahrungsaustausch mit anderen Entwicklern und Anwendern sehr wichtig. Nur so kann ich meine WP-Fähigkeiten verbessern. Mein Un-Vortrag hatte drei Teile:

  1. Performance
  2. Methoden
  3. WordPress

Ich versuche mal, das wichtigste stichpunktartig festzuhalten.

1. Performance

Hier geht es darum, was Performance in Bezug auf (WordPress-)Websites bedeutet.

Speeeeed

Letztendlich bedeutet Performance bei Websites Geschwindigkeit. Je schneller eine Website ist, desto performanter / besser ist sie. Die Hauptfaktoren dabei sind die Übertragungszeiten (Latenz) vom Server zum Client und die Umsetzungszeit (Rendering) im Browser.

UX

Die Nutzererfahrung wird durch die Performance maßgeblich bestimmt. Wie in meinem obigen Erlebnis sicherlich gut nachzuvollziehen. Führt eine langsame Seite zu hohen Absprungraten.

Google-SEO

Last not least ist die Performance (schon seit Anfang 2010!) ein Ranking-Faktor bei den Google-Suchergebnissen.

2. Methoden

Welche Methoden zur Performance-Steigerung bieten sich an.

Rendering optimieren

Hauptsächlich das Rendering Blocking von CSS und Javascript muss geschickt umgangen bzw. vermindert werden:

  • CSS im Header als erstes einbinden
  • JS möglichst am Ende des Footers einbinden und asynchron laden
  • Kleine CSS- und JS-Schnipsel als inline-Code
  • (HIntergrund-)Bilder als Inline-Grafiken oder Sprites

Komprimieren/Minifizieren

Wichtigstes Mittel der Wahl ist natürlich die gzip-Komprimierung. Damit verringert man die Dateigrößen von Dokument, CSS und JS um 50 bis 70%! Beim Minifizieren werden unnötige Leerzeichen, Zeilenumbrüche und Tabs aus dem Code entfernt. Auch Kürzen von z.B. Variablennamen bringt was ein. (uglify)

Kombinieren

Beim Kombinieren geht es v.a. darum, die verschiedenen Script- und Stylesheet-Dateien in jeweils eine Datei zu vereinen. Aber auch mit Bildern geht einiges (siehe Rendering). Das spart Latenz in Form von weniger http-requests.

Caching

Das Vorhalten von Seiten kann auf verschiedenen Weisen erfolgen. Entweder werden statische Dateien der Seiten angelegt oder Datenbankabrufe gespeichert. Manchmal wird erst ein Cache angelegt, wenn jemand zuerst die Seite aufruft und manchmal werden schon vorab Caches angelegt (Priming). Beim Caching ist es wichtig, dass man den richtigen Zeitraum bestimmt, wie lange gecacht werden soll.

usw.usf…. Es gab einige Methoden, auf die ich aus Zeitgründen nicht eingegangen bin. z.B. Bild-Optimierung

3. WordPress

Bisher war der Vortrag eher Theorie-lastig. Aber ohne geht es leider nicht. Im letzen Teil war nun wichtig: Wie kann man das vorher genannte einfach umsetzen?

Wegen der Pragmatik hatte ich mich v.a. auf Pugins bezogen. Die kann man einfach installieren und – meist – optimieren sie schon „out of the box“. Wer allerdings das Letzte aus seiner Seite herausholen möchte, kommt nicht umhin auch mal in der .htaccess zu schreiben oder die Server-Konfiguation aufzupeppen.

Empfehlenswerte Plugins

Caching: W3 Total Cache*, WP Super Cache, Cachify
Kombinieren, Komprimieren: wpCompressor (Ist schon etwas alt, tut aber bisher immer noch seinen Dienst) ,JS & CSS Script Optimizer
Bilder: WP Smush.it

*Dieses Plugin ist zwar sehr mächtig, aber eher für die angebracht, die sich mit Performace Optimierung gut auskennen. Für alle anderen empfehle ich Cachify!

Empfehlenswerte Online-Dienste

Bideroptimierung: Kraken.io (wie Smush.it), TinyPNG
Inline Bilder: Base64 Image Converter

Für den „normalen Hausgebrauch“ ist man damit schon bestens ausgerüstet. Falls ich aber dennoch etwas essentielles Übersehen haben sollte, würde ich mich über Eure Ergänzungen freuen! :-)

Slides Download

Die Slides habe ich auf GitHub abgelegt. Sie sind allerdings noch spärlicher als mein Artikel hier. Es war keine Zeit…. ;-)

https://github.com/HeikoMamerow/wpdm_2014-06-24_unvortrag_performance

WordPress: Frusti, machs gut!

Es ist 0:38 Uhr und ich habe mir soeben alle Blog-Artikel mit samt den Kommentaren und Threads auf Twitter und Google+ zu Caspars Community-Beitrag durchgelesenen. Wirklich alle und gründlich. Es hat sich sehr viel Lesestoff angesammelt. Obwohl der Betrag keine zwölf Stunden draußen war. Also scheint die Community doch nicht ganz so passiv und mitnahmeorientiert zu sein wie vermutet. Puh, Glück gehabt! ;-)

Was mir besonders gut gefällt ist, dass oft von „Nehmen und Geben“ die Rede ist. Das ist sehr tugendhaft und trifft auch meine Intention, wieso ich mich wenigstens um ein klein wenig Aktivismus bei WordPress bemühe. Allerdings scheint mir das allgemeine Verständnis vom „Nehmen und Geben“ irreführend zu sein. Ich gebe etwas, also habe ich irgendwie auch ein Recht darauf etwas zu bekommen. So scheint der Konsens zu sein. Aber auch: Wenn ich immer etwas gebe, aber nie etwas zurück bekomme, dann werde ich eben frustig. Ihr seit schuld!

Oh nein mein Lieber/meine Liebe, denke nicht so! Solche Gedanken werden Dir nicht helfen. Sie werden Dir nur Schaden bringen. Sie machen Dich – über Kurz oder Lang – zum Frusti! 

feelingb

Was erwartest Du eigentlich?

Niemand hat ein Recht auf irgendwas. Man nimmt sich höchstens ein Recht heraus. Der ganze Frust, den ich bei einigen heraus lese, ist nicht darin begründet, dass andere (in diesem Fall die deutsche WP-Community) nicht so sind, wie man es gerne hätte.

Wenn man z.B. jahrein-jahraus an einem Plugin arbeitet. Es ständig den neuen WP-Versionen anpasst und weiter entwickelt. Aber der einzige „Lohn“ sind nörgelnde Anwender im Forum. Dann mag das frustrieren. Aber nur deshalb, weil man erwartet hat, dass man – und sei es auch noch so gering – positive Resonanz erfährt. Das Ego will gefüttert sein….

Enttäuschung führt zu Lustlosigkeit führt zu Frustration führt zu Wut führt zu… Das alles führt dazu, dass man sich schlecht fühlt und unglücklich ist. Unglück entsteht aus nicht erfüllten Wünschen bzw. Vorstellungen. Jedesmal wenn das Leben eine Wendung nimmt, die wir uns nicht wünschen, dann entstehen solche leidvollen Zustände. Je mehr man an seinen Wünschen festhält, desto stärker wirken sie.

Mein Rat ist der, sich gründlich über seine Wünsche bzw. Erwartungen klar zu werden: Was will ich eigentlich? Warum tu ich das? Was erwarte ich? Das ist ein bittere Pille. Denn wer möchte schon zugeben, dass man nur aus selbstwertschätzender Motivation heraus agiert. Dass man Anerkennung haben möchte, einen guten Ruf oder auch Karriere, Geld….

Sich ehrlich über seine Motivation, Wünsche klar zu werden, ist der erste Schritt zur Selbstbestimmung. Leg los!

Frusti, machs gut!

Du sitzt da so allein auf deinem Stuhl
Und schenkst dir einen ein.

Mensch frusti machs gut!

Immer noch sitzt du allein
Auf deinem kleinen kühlen Stein.
Und du denkst über vergangene Zeiten nach
Und du denkst wie es kommen sollte,
Und wie es nicht kam
Das kotzt dich alles so urst an.
Und du denkst was solls
Da trink ich doch noch einen.

Mensch frusti machs gut

Du bist ein cooler Typ
Und ansonsten bist du auch ganz ok
…Aber manchmal…
…Manchmal…
…Da hast du einfach nicht alle machs.

Text von hier.

PS: Jetzt ist es 4:04 Uhr und ich hab den Artikel endlich fertig. Warum mach ich das eigentlich? Was erwarte ich?? ;-)

Grunt: Recursive process.nextTick detected

Ein kleiner, fieser Fehler in Grunt hat mich die letzten Tage schwer beschäftigt. Jedesmal wenn ich einen bestimmten Task aufgerufen habe gab, es eine saftige Fehlermeldung:

(node) warning: Recursive process.nextTick detected. This will break in the next version of node. Please use setImmediate for recursive deferral.

util.js:35
  var str = String(f).replace(formatRegExp, function(x) {
                      ^
RangeError: Maximum call stack size exceeded
Process finished with exit code 7

Mit solchen Meldungen kann niemand was ich nichts anfangen. Das verwirrt nur.

Grunt-Fehlermeldung im Editor

Grunt-Fehlermeldung im Editor

Der obige Fehler tritt auf, wenn im der im Gruntfile.js registrierte TaskName genauso heißt wie ein Task. In meinem Fall war es so:

grunt.registerTask('uglify', ['jshint', 'uglify']);

Die Lösung – wenn man denn erstmal darauf kommt – ist simpel. Einfach den TaskName irgendwie anderes benennen. Bei mir war so der Fehler behoben:

grunt.registerTask('ugly', ['jshint', 'uglify']);

Ohne den Tipp aus Stackoverflow wäre ich wohl nie darauf gekommen. Danke dafür! :-)

PS: Ach ja, wer einen Fehler findet, sollte ihn zuerst immer dem Entwickler mitteilen und dann darüber posten… ;-)

WP-Plugin-Tipp: Tippspiele für die Fußball-Weltmeisterschaft 2014

Die Fußball-Weltmeisterschaft 2014 steht vor der Tür und es mehren sich Anfragen nach einem geeignetem WM-Tippspiel-Plugin für WordPress. Ich habe darum nach Tippspiel-Plugins im WordPress-Repository gesucht und drei Plugins ausgewählt, die mir auf den ersten Blick für die kommende WM am passendsten erschienen.

Kriterien

Meine wichtigsten Entscheidungskriterien waren:

  1. Fertige Datensätze
    Die Tippspiele sollen „WM2014-ready“ sein. Also alle Basisdaten (Manschaften, Spielernamen, Termine usw.) für die kommende WM mitbringen. Denn das nachträgliche Einrichten und Einpflegen der Daten nimmt erfahrungsgemäß sehr viel Zeit in Anspruch.
  2. Sprachunterstützung
    Weil die Zielgruppen meiner Kunden meist deutschsprachig sind, muss ergo mindestens das Frontend auch in deutscher Sprache sein.
  3. Administration
    Einfache Administation der Basisdaten, Tipps, und Benutzer
  4. Einbindung
    Einbindung von Spielständen, Ergebnislisten etc. soll als Shortcode oder Widget möglich sein.
  5. Quizfragen, Preisausschreiben
    Tippspiele werden gerne mit Preisen verbunden. Dass soll sich einfach umsetzen lassen.

Diese Plugins habe ich auf einer lokalen WP-Testinstallation gespielt und verglichen:

World Cup Predictor

Screenshot: Spielübersicht

Screenshot: Spielübersicht

Der Name ist Programm. Dieses Plugin ist im Vergleich zu den anderen am engsten auf die Bedürfnisse eines WM-Tippspiels zugeschnitten und lässt sich – selbst für einen Fußball-Dau wie mich – intuitiv verstehen. Hiermit konnte ich am schnellsten ein fertiges WM-Tippspiel erstellen.

Plugin-Seite: https://wordpress.org/plugins/world-cup-predictor/

Football Pool

Screenshot: Spielplan

Screenshot: Spielplan

Das ist wohl die „Eierlegende Wollmilchsau“ unter den Tippspiel-Plugins. Hiermit kann man viel mehr Tippspiele anbieten als „nur“ zur Fußball-Weltmeisterschaft. Es ist möglich, das Plugin für andere Sportarten oder Meisterschaften anzupassen. Diese Plugin kann ich allen empfehlen, die öfter mal ein Tippspiel auf ihren Websites anbieten möchten.

Plugin-Seite: https://wordpress.org/plugins/football-pool/

wp-championship

Screenshot: Tippspiel

Screenshot: Tippspielübersicht

Das Plugin tut was es soll. Aber unglücklich gelöst finde ich den etwas umständlichen Import der Basisdaten. Die Daten müssen nämlich direkt in der Datenbank hochgeladen werden. Dieser Weg dürfte die meisten Anwender abschrecken. Denn welcher „normalsterbliche“ WP-Anwender hat schon mal eine Datenbank administriert? Aber so schlimm ist es nun auch wieder nicht. Mit dem hervorragenden Datenbankverwaltungs-Plugin Adminer von Frank Bültge schafft sogar jeder „Nicht-Techie“ den Import.

Plugin-Seite: https://wordpress.org/plugins/wp-championship/

Fazit

Alle oben genannten Plugins haben die von mir gewünschten Kriterien erfüllt. Für mich hat World Cup Predictor das Rennen gemacht, weil es am engsten auf die WM zugeschnitten ist. Die anderen Plugins kann man nämlich auch für andere Meisterschaften/Turniere und z.T. sogar für andere Sportarten nehmen. Das macht die Verwaltung allerdings etwas komplexer und erfordert viel mehr Zeit zum Einarbeiten.

CMS-Garden: Meine drei tollen Tage auf der CeBIT

Diese Woche war sehr aufregend und ereignisreich für mich. Ich hatte mir nämlich ein paar freie Tage genehmigt und war von Montag bis Mittwoch zur CeBIT nach Hannover gefahren, um wieder etwas beim CMS-Garden mitzuhelfen.

CMS-Garden

CMS-Garden ist ein gemeinschaftlicher Messestand von verschiedenen Open-Source Content-Management-Systemen (CMS). Ziel des Gartens ist, den Leuten die enormen Fähigkeiten von Open Source CMSen zu zeigen und Entscheidungshilfe bei der Auswahl für ein bestimmtes CMS zu geben.

cms-garden21014-0

Der Stand mit den Terminals.

Der CMSGarden wurde von ehrenamtlichen OpenSource-Enthusiasten aus den jeweiligen CMS-Communitys konzeptioniert, organisiert und durchgeführt. Da steckt sehr viel Herzblut drin aber auch sehr viel Professionalität. Die meisten Betreuer auf der CeBIT waren Entwickler, die ihr CMS sehr gut kannten und sehr gut aus dem eigenen „Nähkästchen“ plaudern konnten.

Unser Publikum am Stand war dafür bunt gemischt. Es kamen sehr viele IT-Entscheider und CMS-Anwender, mit konkreten Fragen zu bestehenden und anstehenden Projekten. Außerdem kamen Schüler, Azubis und Studenten da, die sich freiwillig((!!!) im Rahmen ihres Studiums bzw. Ihrer Ausbildung auf der Messe informiert haben. Zwei Schüler mit denen ich zu tun hatte, kamen sogar über 400km aus Österreich angereist. Viel Spaß hatte ich auch mit ein paar Interessenten, die mit Ihren Laptop vorbei kamen sind um sich vor Ort ein Problem mit der WordPress-Installation bzw. -Plugin beheben zu lassen.

Der Stand

Unser Messestand bestand im Prinzip aus drei Bereichen: Ein Bereich war zum „Anlocken“. Dort lagen die sogenannten Gartenfibeln aus. Ein praktisches Büchlein in dem alle CMS ausführlich vorgestellt wurden und wichtige Themen wie OpenSource, Lizenzierung usw abgehandelt sind. Wenn die Messebesucher sich für die Fibeln interessiert haben, wurden sie von uns angesprochen, ob man Ihnen helfen können. Meist wollten Sie erstmal wissen, was CMS-Garden eigentich ist. Die meisten dachten, wir wären irgend so eine Firma, die etwas zu verkaufen hätte. Entsprechend erstaunt reagierten alle, dass wir wirklich nur helfen wollen.

Der zweite Bereich waren kleine Terminas. Für jedes CMS gab es ein Terminal mit einem virtuelem Host und Internetanschluss. Wen die Leute spezielle Frgen hatten, konnten wir ihnen direkt am CMS eine Lösung zeigen.

Der dritte Bereich war eine kleine Präsentationsfläche, wo von Zeit zu Zeit Präsentationen für CMSe gemacht wurden.

Reich

Die größte Bereicherung für mich war das Kennenlernen von vielen interessanten Menschen. Ganz besonder gefreut habe ich mich, über den persönlichen Kontakt zu meinen „Standkollegen“ Jan ReimersFrank Staude und Sven Wagener.

cms-garden21014-3

Frank, Jan und Jens bei der „Lagebesprechung“ am ersten Tag

Die sehe ich sicherlich bald in Hamburg wieder… :-)