Aktuelle Position der Alex II

Dank modernster Technik kann ich jetzt stündlich die Position der „Alexander von Humboldt II“ aktualisieren und auf einer Karte darstellen – und zwar auch mitten auf dem Ozean, fernab der Reichweite aller (landgestützen) Systeme, die ich bisher zur Verfügung hatte .

[pageview url=“https://track.alex-2.info/alextracker.php“ height=“460px“]

Die Wetterdaten (Temperatur, Luftdruck, Wind) werden stündlich für die gemeldete Position von openweathermap abgerufen und in die Karte eingearbeitet; die letzten Positionen sind als rote Linie sichtbar. Über die Schaltfläche oben rechts kann die Kartendarstellung verändert werden.

PageSpeed von 68 auf 91 in 5 Minuten

Google PageSpeed ist ja nach wie vor eine wichtige Messlatte, wenn es um Seitenoptimierung geht. Auf gute Werte zu kommen, ist gar nicht so schwierig – es dauert nur ein paar Minuten, um zumindest in den grünen Bereich zu kommen.

Ich habe es mal auf einer Demoseite (WP 4.9.1) mit einem Standardtheme (twentyseventeen) ausprobiert und konnte tatsächlich nach ein paar Minuten deutlich gesteigerte Bewertungen sehen:
Mobil „ab Werk“ 68%, gesteigert auf 91%
Desktop „ab Werk“ 74%, gesteigert auf 97%

Ohne Plugins geht es nicht, ich habe folgende Plugins verwendet:

  • Autoptimize
    optimiert lediglich HTML und CSS (auch inline)
  • Responsify WP
    läuft mit den Standardeinstellungen
  • WP Super Cache
    läuft mit Experteneinstellungen (Seiten komprimieren, Header cachen), der Cache wurde manuell vorgeladen

Zusätzlich habe ich in der .htaccess nochmal explizit die Komprimierung aktiviert und das Ablaufdatum erhöht:

# BEGIN browser caching
<FilesMatch "\.(html|htm)$">
  FileETag None
  <ifModule mod_headers.c>
    Header unset ETag
    Header set Cache-Control "max-age=0, no-cache, no-store, must-revalidate"
    Header set Pragma "no-cache"
    Header set Expires "Mon, 29 Oct 1923 20:30:00 GMT"
  </ifModule>
</FilesMatch>

# BEGIN Gzip
<IfModule mod_deflate.c>
  AddOutputFilterByType DEFLATE image/svg+xml
  AddOutputFilterByType DEFLATE image/ico
  AddOutputFilterByType DEFLATE image/x-icon
  AddOutputFilterByType DEFLATE text/plain
  AddOutputFilterByType DEFLATE text/html
  AddOutputFilterByType DEFLATE text/xml
  AddOutputFilterByType DEFLATE text/css
  AddOutputFilterByType DEFLATE text/javascript
  AddOutputFilterByType DEFLATE application/xml
  AddOutputFilterByType DEFLATE application/xhtml+xml
  AddOutputFilterByType DEFLATE application/rss+xml
  AddOutputFilterByType DEFLATE application/javascript
  AddOutputFilterByType DEFLATE application/x-javascript
  AddOutputFilterByType DEFLATE application/x-font-ttf
  AddOutputFilterByType DEFLATE application/vnd.ms-fontobject
  AddOutputFilterByType DEFLATE font/opentype font/ttf font/eot font/otf
</IfModule>
# END Gzip
# BEGIN LBC
<FilesMatch "\.(ico|pdf|flv|jpg|jpeg|png|gif|js|css|swf|x-html|css|xml|js|woff|woff2|ttf|svg|eot)(\.gz)?$">
  <IfModule mod_expires.c>
    ExpiresActive On
    ExpiresDefault A0
    ExpiresByType image/gif "access plus 1 month"
    ExpiresByType image/png "access plus 1 month"
    ExpiresByType image/jpg "access plus 1 month"
    ExpiresByType image/jpeg "access plus 1 month"
    ExpiresByType image/ico "access plus 1 month"
    ExpiresByType image/x-icon "access plus 1 month"
	ExpiresByType image/vnd.microsoft.icon "access plus 1 month"
    ExpiresByType text/css "access plus 1 month"
    ExpiresByType text/javascript "access plus 1 month"
	ExpiresByType text/html "access plus 1 month"
	ExpiresByType text/plain "access plus 1 month"
    ExpiresByType application/javascript "access plus 1 month"
    ExpiresByType application/x-javascript "access plus 1 month"
    ExpiresByType application/ico "access plus 1 month"
    ExpiresByType application/x-icon "access plus 1 month"
	ExpiresByType application/x-shockwave-flash "access plus 1 month"
	ExpiresByType application/xhtml-xml "access plus 600 seconds"
  </IfModule>
  <IfModule mod_headers.c>
    Header set Expires "max-age=2592000, public"
    Header unset ETag
    Header set Connection keep-alive
  </IfModule>
  FileETag None
</FilesMatch>
# END LBC
# END browser caching

<IfModule mod_headers.c>
  <FilesMatch "\.(js|css|xml|gz)$">
    Header append Vary: Accept-Encoding
  </FilesMatch>
</IfModule>

Das war schon alles

Ja wirklich.

Autoptimize brachte mobil 70%, Desktop 77%.
WP Super Cache brachte mobil 85%, Desktop 93%
Cache vorgeladen brachte dann die letzten Punkte: mobil 91%, Desktop 97%

come to the geek side

I can explainSprüche auf T-Shirts sind ja fast schon wieder out, aber manchmal trifft es eben doch den Nagel auf den Kopf. Dieser Tage hatte ich so einen Moment der Erkenntnis – DER passende Spruch zur aktuellen Situation, besser kann man es manchmal nicht ausdrücken.

Kurzum: der Shop ist es wert, verlinkt zu werden.

Und damit es neben der persönlichen Belustigung auch einen guten Zweck hat, wird der Link über das Boost Project geschaltet, d.h. ein Teil des gemachten Umsatzes wird vom Shopbetreiber direkt an die „Alexander von Humboldt II“ gespendet – ohne Mehrkosten für den Besteller, einfach so im Hintergrund.

getdigital banner

11 Rules of Life

Someone gave a speech at a High School about eleven things they did not and will not learn in school.
He talks about how feel-good, politically correct teachings created a generation of kids with no concept of reality and how this concept set them up for failure in the real world.

  1. Life is not fair – get used to it!
  2. The world doesn’t care about your self-esteem.
    The world will expect you to accomplish something BEFORE you feel good about yourself.
  3. You will NOT make $60,000 a year right out of high school.
    You won’t be a vice-president with a car phone until you earn both.
  4. If you think your teacher is tough, wait till you get a boss.
  5. Flipping burgers is not beneath your dignity.
    Your Grandparents had a different word for burger flipping: They called it opportunity.
  6. If you mess up, it’s not your parents‘ fault, so don’t whine about your mistakes, learn from them.
  7. Before you were born, your parents weren’t as boring as they are now. They got that way from paying your bills, cleaning your clothes and listening to you talk about how cool you thought you were: So before you save the rain forest from the parasites of your parent’s generation, try delousing the closet in your own room.
  8. Your school may have done away with winners and losers, but life HAS NOT. In some schools, they have abolished failing grades and they’ll give you as MANY TIMES as you want to get the right answer.
    This doesn’t bear the slightest resemblance to ANYTHING in real life.
  9. Life is not divided into semesters.
    You don’t get summers off and very few employers are interested in helping you FIND YOURSELF. (Do that on your own time.)
  10. Television is NOT real life.
    In real life, people actually have to leave the coffee shop and go to jobs.
  11. Be nice to nerds. Chances are you’ll end up working for one.

(found it on Facebook and worth keeping)

Mit Sicherheit: Umstellung auf https

SSL ist in aller Munde, gesichert aufrufbare Seiten bekommen Pluspunkte beim Ranking – Grund genug, sich mal näher mit der Materie zu beschäftigen.

Alles fängt damit an, dass man ein gültiges SSL-Zertifikat hat… Über meinen Hoster konnte ich mir ein selbst signiertes Zertifikat ausstellen – das bringt aber nur wenig, weil es vom Browser erstmal nicht automatisch anerkannt wird. Wie denn auch, schließlich ist die Sicherheit ja nicht durch irgendeine anerkannte Instanz bestätigt.

Zum Glück gibt es im Internet ja auch Anbieter, bei denen man gültige Zertifikate für kleines Geld bekommt; von den kostenlosen Zertifikaten von StartSSL bin ich wieder abgerückt, nachdem ich diesen Artikel gelesen hatte. Schließlich soll das ja erstmal nur ein Test sein, da möchte ich nicht im Zweifel gleich Kosten an der Backe haben, wenn ich mich dann doch gegen SSL entscheide.

Eine kurze Recherche brachte mich dann zu cheapsslshop.com: die verkaufen nicht nur die (hauseigenen) Zertifikate von Comodo für wesentlich weniger Geld als Comodo selbst , sondern auch Zertifikate anderer Anbieter (Thawte, GlobalSign, …). Im Zweifel kann man da also auch für den professionellen Einsatz fündig werden und seiner Website eine grüne Adresszeile spendieren. Soviel brauche ich aber nicht, mir reicht eine einfache Bestätigung. Bezahlung klappt mit Paypal, es gibt eine 30-tägige Testphase innerhalb derer man komplett vom Kauf zurücktreten kann und das Zertifikat selbst kam innerhalb von ein paar Minuten per Mail – mit Installation auf dem Server hat es nicht mal eine halbe Stunde gedauert, bis die Seite grundsätzlich auch via https erreichbar war. Wiedermal war ich froh, cPanel als Backend zur Administration zu haben und nicht auf eine Provider-spezifische Lösung angewiesen zu sein: mit ein paar Klicks ist die Anforderung (CSR) erzeugt, mit ein paar weiteren Klicks ist das fertige Zertifikat dann installiert.

Update:
Seit dem Umzug zu WebhostOne habe ich zwar kein cPanel mehr zur Verfügung, dafür aber die Möglichkeit, ein kostenloses Zertifikat von Let’s Encrypt einzubinden.

Das ist ja aber leider erst die halbe Miete, WordPress erfordert ja auch noch ein paar Einstellungen bevor es wirklich komplett und ausschließlich über gesicherte Verbindungen arbeitet:

  • interne Links unabhängig vom Protokoll
    Als erste Maßnahme wurden sämtliche internen Links in den Widgets und Theme-Dateien/-Einstellungen vom Protokollaufruf befreit: statt

    http://mysite.net/

     steht jetzt nur noch

    //mysite.net/

     im Code – somit kann diese Ressource gesichert oder ungesichert aufgerufen werden, ohne dass der Browser eine Fehlermeldung wegen gemischter Inhalte auswirft.

  • http auf https umleiten
    Das erfordert ein paar zusätzliche Zeilen in der .htaccess. Bei der Gelegenheit fällt auf, dass jede Menge Einträge zum Caching in der Datei stehen, die allesamt noch mit ungesicherter Verbindung arbeiten – also erstmal das Caching-Plugin deaktivieren, damit diese ganzen Regeln verschwinden. Wenn alle Einstellungen auf https gesetzt sind, wird Caching wieder aktiviert und schreibt dann automatisch die gesicherten Rewrite Rules.
    Damit Besucher und Suchmaschinen sich auch den neuen gesicherten Aufruf merken, bekommen sie gleiche einen Returncode 301 (permanent redirect) mitgeliefert; beim nächsten Besuch sollte dann direkt die gesicherte Seite aufgerufen werden.

    # BEGIN redirect all to https
    RewriteEngine On
    RewriteCond %{HTTPS} off
    RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
    # END redirect all to https
  • URLs in der Datenbank umstellen
    WordPress speichert etliche URLs in der Datenbank, natürlich komplett mit Protokoll – die sollte man ebenfalls von http:// auf https:// umstellen, um sich unerwartete Probleme an anderen Stellen zu ersparen.
    Dazu habe ich im Web drei passende SQL-Anweisungen gefunden, die man nach einer Sicherung (!!) einfach über die eigene Datenbank laufen lassen kann:

    UPDATE wp_posts SET guid = replace(guid, 'http://www.site.com','https://www.site.com');
    UPDATE wp_posts SET post_content = replace(post_content, 'http://www.site.com', 'https://www.site.com');
    UPDATE wp_postmeta SET meta_value = replace(meta_value, 'http://www.site.com', 'https://www.site.com');

    Und ein praktisches Beispiel, warum man das tun sollte habe ich auch: Wie schon an anderer Stelle geschrieben habe ich auch die Titelbilder hier im Blog responsive gemacht. Das ging aber nur mit einem kleinen Trick, ich mußte aus der Bild-URL die ID in der Datenbank bestimmen. Genau an der Stelle wird es problematisch, wenn WP eine https:// URL vorgibt und in der Datenbank nur http:// steht – auf einmal ist das Titelbild weg

  • WordPress umstellen
    Zu guter Letzt werden in den allgemeinen Einstellungen noch die URLs (WordPress-Adresse und Website-Adresse) auf https geändert.
    Wer mag, kann auf jeden Fall eine gesicherte Verbindung für die Administration erzwingen, indem er folgende Zeile in die wp-config.php (irgendwo vor /* That's all, stop editing!) einfügt:
    [php]define(‚FORCE_SSL_ADMIN‘, true);[/php]

Im Idealfall läuft jetzt alles korrekt – falls nicht, muss man sich auf Fehlersuche machen ;-).
Manchmal hilft schon ein Blick in den Quellcode der Seite, um die letzten http:// Aufrufe zu finden….

quo vadis, Facebook?

Facebook war ja noch nie dafür bekannt, Nutzer- und Nutzungsdaten sparsam zu erhebn (und zu verwerten). Und die recht strikten deutschen Datenschutzbestimmungen dürften bei Facebook auch kaum mehr als ein müdes Lächeln hervorrufen – dass in diesem Zusammenhang deutsche Datenschutzbedenken zahnlose Papiertiger sind, hat man ja in der Vergangenheit schon erlebt.

Aber ganz offensichtlich bekommt Facebook den Hals nicht voll, wenn es ums Datensammeln geht – alles natürlich einzig und allein zum Wohl der Nutzer, um ihr Nutzungserlebnis zu verbessern. Zu diesem Zweck soll übermorgen die nächste AGB-Änderung in Kraft treten, mit der Nutzung von Facebook erkennt man automatisch die neuen AGB an. Wer nicht mit allen Bedingungen einverstanden ist, muss seinen Account löschen. Ganz oder garnicht ist mal wieder die Devise.

Eigentlich habe ich mich – wie vermutlich die meisten anderen User auch – nicht weiter mit dem Thema beschäftigt und wollte es einfach achselzuckend über mich ergehen lassen. Obwohl die Formulierung „…du erklärst dich … damit einverstanden, dass du verbesserte Werbeanzeigen siehst, die auf den von dir genutzten Apps und Webseiten basieren“ einen schon hellhörig werden läßt bzw. lassen sollte.
Aber dann bin ich durch einen Post bei Facebook doch ins Grübeln gekommen. Eine Freundin kündigte die Löschung ihres Accounts an und verlinkte in ihrem Beitrag auf den Nachtwächter, der sich die neuen AGB mal genauer durchgelesen hat (und zur gleichen Entscheidung gekommen ist). Ganz kurz zusammengefasst ein paar Highlights:

  • FB sammelt Informationen durch und über die Computer und sonstigen Geräte, „auf denen du unsere Dienste installierst bzw. durch die du auf sie zugreifst. Wir können die Informationen, die wir von deinen unterschiedlichen Geräten sammeln, miteinander in Verbindung bringen… Hier sind einige Beispiele für Geräteinformationen, die wir sammeln:
    Attribute wie Betriebssystem, Hardware-Version, Geräteeinstellungen, Datei- und Software-Namen und -Arten, Batterie- und Signalstärke sowie Gerätekennungen. Gerätestandorte, einschließlich spezieller geografischer Orte, beispielsweise über GPS, Bluetooth oder WLAN-Signale. Verbindungsinformationen, wie Name deines Mobilfunk- oder Internetdienstanbieters, Browsertyp, Sprache und Zeitzone, Handynummer und IP-Adresse.
  • Wir sammeln Informationen, wenn du Webseiten und Apps Dritter besuchst, die unsere Dienste nutzen (z. B. wenn sie unsere „Gefällt mir“-Schaltfläche oder die Facebook-Anmeldung anbieten oder unsere Bewertungs- und Werbedienste nutzen). Dazu zählen auch Informationen über die von dir besuchten Webseiten und Apps…
  • Wir erhalten von Drittpartnern Informationen über dich und deine Aktivitäten auf und außerhalb von Facebook; beispielsweise von einem Partner, wenn wir gemeinsam Dienste anbieten, oder von einem Werbetreibenden über deine Erfahrungen oder Interaktionen mit ihm.

Klar, als angemeldeter User bin ich bei Facebook nicht der Kunde sondern die Ware – aber dennoch finde ich den Umfang der angepeilten Datensammlung doch einigermaßen erschreckend. Die gesammelten Daten sind (kostbare) Handelsware und können von Facebook nach deren Gutdünken beliebig weitergegeben und vermarktet werden – egal an wen. Geradezu dreist finde ich die Ausführungen dazu, was mit den gesammelten Daten alles gemacht wird, vor allem die Aushebelung sämtlicher gesetzlicher Schutzrechte per AGB:

“Als Reaktion auf eine rechtliche Anfrage (zum Beispiel ein Durchsuchungsbefehl, eine gerichtliche Verfügung oder Vorladung) dürfen wir auf deine Informationen zugreifen, diese aufbewahren oder an Dritte weitergeben, wenn wir in gutem Glauben der Ansicht sind, dass wir rechtlich hierzu verpflichtet sind.”

“Wir dürfen ebenfalls auf Informationen zugreifen, diese aufbewahren oder an Dritte weitergeben, wenn wir in gutem Glauben der Ansicht sind, dass dies erforderlich ist, um: Betrug und sonstige illegale Aktivitäten aufzudecken, zu verhindern oder zu verfolgen…”

Fazit

Ob ich meinen Account jetzt wirklich lösche, weiß ich noch nicht – aber ich denke ernsthaft darüber nach, die App vom Smartphone zu verbannen. Schlimm genug, dass WhatsApp da noch drauf läuft, obwohl ich auch einen Account bei Threema habe und nutze. Am PC läuft Facebook wenn überhaupt immer nur alleine in einer „privaten“ Session; auch da werde ich mir mal noch über zusätzliche Sicherungen ein paar Gedanken machen.

Eins steht aber jetzt schon fest: ich möchte mich nicht auch noch aktiv an der Datensammlung beteiligen und entferne mit sofortiger Wirkung alle Verbindungen zwischen diesem Blog und Facebook. Lob und Kritik kann man immer noch in den Kommentaren hinterlassen, das geht auch ohne Anmeldung. Und wer einen Artikel weiterverbreiten will kann das wegen mir gerne mit copy & paste aus der Adresszeile erledigen.

PS: Ja, der Link zu meinem Facebook-Profil ist immer noch da. Es ist nur ein ausgehender Link, der in einem neuen Browserfenster geöffnet wird – die bloße Sichtbarkeit dieser Verlinkung führt nicht dazu, dass Facebook auf dieser meiner Seite irgendwelche Aktivitäten durchführt.

Responsive Images im Eigenbau

Bei den Performance-Messungen im Zuge meines Wechsels von Yoko zu Catch Evolution bekam ich immer wieder den Optimierungshinweis, auch im Header doch angepasste Grafiken („responsive images“) auszuliefern, statt standardmäßig immer das gleiche Bild mit 1600×400 Pixeln in voller Größe auch auf die kleinsten Endgeräte zu schicken.

Die Idee ist nicht schlecht, auch wenn sich der Effekt durch Smartphones mit immer höheren Auflösungen wahrscheinlich immer weniger auswirken wird. Aber egal, es ist eine nette kleine Fingerübung und bringt wieder ein paar zusätzliche Punkte in der Bewertung – die kann man ja en passant mitnehmen. Auch auf einer so wenig besuchten Website wie dieser hier.

Falls es mal jemand nachbauen möchte steht hier mein Lösungsansatz. Bilder innerhalb der Beiträge habe ich mit Responsify WP umgestellt, nur beim Header musste ich selbst Hand anlegen.

Schritt 1:
Media Breakpoints festlegen bzw. finden

Das Catch Evolution Theme ist ja schon responsive ausgelegt und reagiert auf unterschiedliche Bildschirmauflösungen. Also werfen wir mal einen Blick ins css, genauer gesagt in die wp-content/themes/catch-evolution/css/responsive.css und suchen nach @media, um die „Umschaltpunkte“ zu finden:

[css gutter=“0″]@media screen and (max-width: 960px) {
@media screen and (max-width: 767px) {
@media screen and (max-width: 479px) {
@media screen and (max-width: 320px) {
@media screen and (max-width: 1224px) {
@media screen and (max-width: 1060px) {[/css]

Und schon wissen wir, ab welcher Auflösung sich das Layout ändert und wir ein kleineres Titelbild ausliefern lassen könnten. Der Einfachheit halber geben wir jedesmal ein anderes Bild aus.
WordPress kennt standardmäßig nur drei Bildgrößen (festgelegt unter Einstellungen – Medien): Thumbnail, Mittel, Groß. Das ist schonmal ein Anfang, diese Größen legen wir wie folgt fest: Thumbnail 150, Mittel 468, Groß 680px breit, jeweils mit proportionaler Höhe.
media_settings
Da wir hier noch ein paar Zwischengrößen brauchen, definieren wir uns einfach welche mit add_image_size(). Das Titelbild wird immer in voller Breite ohne irgendwelche Ränder ausgegeben, deswegen übernehmen wir einfach die Umschaltpunkte von oben. Konkret fügen wir in die functions.php unseres Child Themes folgende Zeilen ein:

[php title=“>>> functions.php“ padlines=“1″]// headers are 1600×400 or a fraction thereof, so all must be hard cropped
add_image_size(‚resp-head-full‘, 1600, 400, true); //this is the maximum size we want for header images
add_image_size(‚resp-head-xlarge‘, 1224, 306, true);
add_image_size(‚resp-head-large‘, 1059, 264, true);
add_image_size(‚resp-head-medium‘, 960, 240, true);
add_image_size(‚resp-head-small‘, 767, 191, true);
add_image_size(‚resp-head-xsmall‘, 467, 116, true);
add_image_size(‚resp-head-mini‘, 320, 80, true);

// others are just restricted in width
add_image_size(‚resp-large‘, 592, 9999);
add_image_size(‚resp-small‘, 320, 9999);
add_image_size(‚resp-mini‘, 278, 9999);[/php]

So ist sichergestellt, dass die Titelbilder alle auf jeden Fall im richtigen Seitenverhältnis vorliegen, auch wenn das Artikelbild („featured image“) automatisch in den Titel übernommen wird. Diese Funktionalität ist im Catch Evoltion schon enthalten (in Yoko übrigens auch). Die Funktion hat vier Parameter: add_image_size( $name, $width, $height, $crop )

  • $name ist der Name, unter dem das Format gezielt angesprochen werden kann
  • $width, $height sind die Abmessungen; ein Wert muss angegeben werden, wenn das Bild proportional verkleinert werden soll, wird der andere mit 9999 angegeben
  • $crop legt fest, ob proportional verkleinert oder absolut beschnitten werden soll.

Für das Format „resp-header-full“ wird ein Bild also immer auf 1600x400px beschnitten, für „resp-mini“ wird das Bild proportional auf eine Breite von 278px verkleinert. (Die drei proportionalen Breiten 278, 320 und 592px verwende ich mit Responsify-WP im Textteil, für die Titelbilder werden sie nicht genutzt)

Alternativ kann man sich natürlich auch an den gängigsten Bildschirmauflösungen seiner Besucher orientieren und die Bildgrößen darauf optimieren

[php title=“>>> functions.php“ padlines=“1″]// headers are 1600×400 or a fraction thereof, so all must be hard cropped
add_image_size(‚resp-head-full‘, 1600, 400, true); //this is the maximum size we want for header images
add_image_size(‚resp-head-1440‘, 1440, 360, true);
add_image_size(‚resp-head-1366‘, 1366, 341, true);
add_image_size(‚resp-head-sxga‘, 1280, 320, true);
add_image_size(‚resp-head-xga‘, 1024, 256, true);
add_image_size(‚resp-head-medium‘, 960, 240, true);
add_image_size(‚resp-head-720‘, 720, 180, true);
add_image_size(‚resp-head-xsmall‘, 467, 116, true);
add_image_size(‚resp-head-mini‘, 320, 80, true);[/php]

Mit dem Plugin Regenerate Thumbnails können dann für alle Bilder in der Mediathek die neuen Bildgrößen mit ein paar Klicks automatisch erzeugt werden; neu hochgeladene Bilder werden sofort automatisch in alle Größen konvertiert.

Schritt 2:
picturefill.js einbinden

Eine Anmerkung vorab: solange das Plugin Responsify WP aktiv ist, kann dieser Schritt übersprungen werden; das Plugin bindet die picturefill.js selbst ein.

Ich habe mich für die alte Version 1.2 entschieden, da sie auf jeden Fall auch mit älteren Browsern kompatibel ist, die das neue picture Element noch nicht verstehen. Runterladen kann man das Skript direkt bei Github; Archiv entpacken und die picturefill.js aus dem Verzeichnis dist in den (Child-)Theme Ordner hochladen. Wenn man es ganz elegant machen will, erzeugt man sich vorher noch einen Unterordner /js und lädt die Datei dort hoch.

Damit die Datei auch geladen wird und verwendet werden kann, muss sie in WordPress eingehängt werden. Das ist ebenfalls wieder mit ein paar Zeilen Code in der functions.php erledigt (ggf. den Pfad anpassen!):

[php padlines=“1″ title=“>>> functions.php“]function add_picturefill(){
wp_enqueue_script( ‚picturefill_header‘, get_stylesheet_directory_uri() . ‚/js/picturefill.js‘, array(), ‚1‘ );
}

add_action(‚wp_enqueue_scripts‘, ‚add_picturefill‘);[/php]

Schritt 3:
statische Titelbilder austauschen

Zuerst die alles entscheidende Frage: Wo und wie genau wird das Titelbild eingebunden? Meistens passiert das in der header.php, bei Catch Evolution passiert es über die Funktion catchevolution_featured_header(), die sich in wp-content/themes/catch-evolution/inc/custom_header.php versteckt:

[php title=“>>> custom_header.php“ firstline=“390″ highlight=“410,414″]/**
* Header Image
*
* Uses Custom Header and Featued Images
* @Hooked in catchevolution_headercontent
* @since Catch Evolution 1.0
*/
function catchevolution_featured_header() {
global $wp_query, $post, $paged, $_wp_default_headers;

// Header Image
$header_image_path = get_header_image();

// Check if this is a post or page, if it has a thumbnail, and if it’s a big one
if ( is_singular() && current_theme_supports( ‚post-thumbnails‘ ) &&
has_post_thumbnail( $post->ID ) &&
( /* $src, $width, $height */ $image = wp_get_attachment_image_src( get_post_thumbnail_id( $post->ID ), ‚post-thumbnail‘ ) ) &&
$image[1] >= HEADER_IMAGE_WIDTH ) :
// Houston, we have a new header image!
echo ‚<div id="header-image">‘;
echo get_the_post_thumbnail( $post->ID );
echo ‚</div>‘;
elseif ( get_header_image() ) : ?>
<div id="header-image">
<img src="<?php header_image(); ?>" width="<?php echo get_custom_header()->width; ?>" height="<?php echo get_custom_header()->height; ?>" alt="" />
</div>
<?php endif;

} // catchevolution_featured_header[/php]

Wie oben schon angesprochen verwendet das Theme automatisch das Artikelbild, wenn dieses mindestens 1600 Pixel breit ist – deswegen müssen wir an zwei Stellen eingreifen.

Picturefill.js funktioniert nur mit der post_id des angehängten Bildes, header_image() liefert aber die URL – also brauchen wir zuerst noch eine kleine Funktion, die uns aus der URL die ID liefert. Auch diese Funktion kommt in die functions.php:

[php padlines=“1″ title=“>>> functions.php“]function get_attachment_id_from_src($url) {
global $wpdb;
$prefix = $wpdb->prefix;
$attachment = $wpdb->get_col($wpdb->prepare("SELECT ID FROM " . $prefix . "posts" . " WHERE guid=’%s‘;", $url ));
return $attachment[0];
}[/php]

Zu guter Letzt wird die umgebaute Funktion catchevolution_featured_header() eingebaut, ebenfalls wieder in functions.php. Mehr Varianten dazu hat Stefan Ledin mit Responsify-WP auf Github beschrieben.

[php padlines=“1″ title=“>>> functions.php“ highlight=“14,15,16,21-25″]function catchevolution_featured_header() {
global $wp_query, $post, $paged, $_wp_default_headers;

// Header Image
$header_image_path = get_header_image();

// Check if this is a post or page, if it has a thumbnail, and if it’s a big one
if ( is_singular() && current_theme_supports( ‚post-thumbnails‘ ) &&
has_post_thumbnail( $post->ID ) &&
( /* $src, $width, $height */ $image = wp_get_attachment_image_src( get_post_thumbnail_id( $post->ID ), ‚post-thumbnail‘ ) ) &&
$image[1] >= HEADER_IMAGE_WIDTH ) :
// Houston, we have a new header image!
echo ‚<div id="header-image">‘;
$thumbnail_id = get_post_thumbnail_id( $post->ID );
echo Picture::create( ‚element‘, $thumbnail_id, array(’sizes‘ => array( ‚resp-head-mini‘, ‚resp-head-xsmall‘, ‚resp-head-small‘, ‚resp-head-medium‘, ‚resp-head-large‘, ‚resp-head-xlarge‘, ‚resp-head-full‘ )
) );
echo ‚</div>‘;
elseif ( get_header_image() ) : ?>
<div id="header-image">
<?php
$header_id = get_attachment_id_from_src($header_image_path);
echo Picture::create( ‚element‘, $header_id, array(
’sizes‘ => array( ‚resp-head-mini‘, ‚resp-head-xsmall‘, ‚resp-head-small‘, ‚resp-head-medium‘, ‚resp-head-large‘, ‚resp-head-xlarge‘, ‚resp-head-full‘, ‚full‘ )
)
);
?>
</div>
<?php endif;
} // catchevolution_featured_header[/php]

Wer nicht automatisch das Artikelbild auch als Titelbild verwenden möchte, lässt einfach ein paar Zeilen weg:

[php padlines=“1″ title=“>>> functions.php“ highlight=“8,9-12″]function catchevolution_featured_header() {
global $wp_query, $post, $paged, $_wp_default_headers;

// Header Image
$header_image_path = get_header_image(); ?>
<div id="header-image">
<?php
$header_id = get_attachment_id_from_src($header_image_path);
echo Picture::create( ‚element‘, $header_id, array(
’sizes‘ => array( ‚resp-head-mini‘, ‚resp-head-xsmall‘, ‚resp-head-small‘, ‚resp-head-medium‘, ‚resp-head-large‘, ‚resp-head-xlarge‘, ‚resp-head-full‘, ‚full‘ )
)
);
?>
</div>
<?php
} // catchevolution_featured_header[/php]

Schritt 4:
Erfolgskontrolle

Kontrollieren lässt sich das Ergebnis im Browser: in der Quellcode-Ansicht steht statt

[code lang=“html“]<div id="header-image">
<img src="http://domain.tld/wp-content/uploads/headerimage.jpg" …>
</div>[/code]

jetzt ein ganzer Satz von möglichen Bildern, die vom Browser intelligent passend zur aktuellen Auflösung geladen werden:

[code lang=“html“]<div id="header-image">
<span data-picture data-alt="">
<span data-src="http://domain.tld/wp-content/uploads/headerimage-320×80.jpg" ></span>
<span data-src="http://domain.tld/wp-content/uploads/headerimage-467×116.jpg" data-media="(min-width: 320px)" ></span>
<span data-src="http://domain.tld/wp-content/uploads/headerimage-767×191.jpg" data-media="(min-width: 467px)" ></span>
<span data-src="http://domain.tld/wp-content/uploads/headerimage-960×240.jpg" data-media="(min-width: 767px)" ></span>
<span data-src="http://domain.tld/wp-content/uploads/headerimage-1059×264.jpg" data-media="(min-width: 960px)" ></span>
<span data-src="http://domain.tld/wp-content/uploads/headerimage-1224×306.jpg" data-media="(min-width: 1059px)" ></span>
<span data-src="http://domain.tld/wp-content/uploads/headerimage.jpg" data-media="(min-width: 1224px)" ></span>
<noscript><img src="domain.tld/wp-content/uploads/headerimage-320×80.jpg" alt=""></noscript>
</span>
</div>[/code]

Wenn man die Größe des Browserfensters ändert, ändert sich auch die URL des Titelbilds.

Achtung: picturefill.js hat bei mir nicht mehr funktioniert, als ich es asynchron mit defer='defer' geladen habe; auch die Zusammenfassung mit anderen eingebundenen js-Dateien hat zu Problemen geführt – ggf. muss man beim Einsatz eines Caching-Plugins also darauf achten. Laden im Footer hat keinen negativen Einfluss.

Bei der Umsetzung geholfen haben mir die Erläuterungen zu Responsify-WP, dieser Artikel von wpmudev und ein paar Tassen Kaffee 😉

WordPress Performance

Auch so ein Thema, zu dem schon viel geschrieben wurde… Ich will mich gar nicht lange mit Details aufhalten – hier sind meine Testergebnisse mit den gängigen Webtools (zuletzt geprüft am 19.09.2014).

Zuerst die Werte der alten Seite mit Yoko als Vergleich (Cache aktiviert)

Das neue Theme ohne Titelbilder mit deaktiviertem Cache liefert

  • Google PageSpeed Insights:
    mobil 78/100, Nutzererfahrung 89/100, Desktop 92/100
  • Pingdom Website Speed Test: 98/100
  • GTmetrix: PageSpeed grade A (90%), YSlow grade B (87%)
  • WebPagetest.org
    first byte time: F, Keep-alive: A, compress transfer: A, compress images: A, cache static content: C

Mit aktiviertem Cache ergeben sich nur leicht andere Ergebnisse:

  • Google PageSpeed Insights
    mobil 78/100, Nutzererfahrung 89/100, Desktop 92/100
  • Pingdom Website Speed Test: 97/100
  • GTmetrix: PageSpeed grade A (95%), YSlow grade A (92%)
  • WebPagetest.org
    first byte time: A, Keep-alive: A, compress transfer: A, compress images: A, cache static content: B

Mal sehen, ob und wie weit sich das in Zukunft noch verbessern läßt und wie sich die Titelbilder auf die Performance auswirken…

[update 22.09.2014]
Nachdem jetzt auch Titelbilder angezeigt werden, wird es Zeit für eine neue Messung, natürlich mit aktiviertem Cache. Die Titelbilder haben bei Catch Evolution immerhin 65% mehr Pixel, das dürfte sich trotz Optimierung irgendwie bemerkbar machen – jedenfalls solange ich noch nicht auf echte responsive images umgestellt habe.

  • Google PageSpeed Insights
    mobil 72/100, Nutzererfahrung 89/100, Desktop 91/100
  • Pingdom Website Speed Test: 100/100
  • GTmetrix: PageSpeed grade B (86%), YSlow grade A (92%)
  • WebPagetest.org
    first byte time: B, Keep-alive: A, compress transfer: A, compress images: B, cache static content: A

Unterm Strich hat sich die Umstellung auf ein anderes Theme zumindest im Hinblick auf die Performance schonmal gelohnt.

Nicht zu verachten sind natürlich auch die Hinweise der diversen Tools, wie die Performance verbessert werden kann. GTmetrix bietet z.B. gleich optimierte Versionen von noch nicht ganz optimalen Bildern an, die kann man dann gleich in die eigene Mediathek übernehmen…

[update 26.09.2014]
Inzwischen sind auch die Bilder komplett auf angepasste Formate („responsive images“) umgestellt, was sich zusammen mit noch ein paar zusätzlichen Optimierungen sehr positiv auf die Messwerte auswirkt:

  • Google PageSpeed Insights
    mobil 84/100, Nutzererfahrung 89/100, Desktop 92/100
  • Pingdom Website Speed Test: 100/100 (load time 1,17s)
  • GTmetrix: PageSpeed grade A (97%), YSlow grade A (90%)
  • WebPagetest.org
    first byte time: A, Keep-alive: A, compress transfer: A, compress images: B, cache static content: B
    First view: 2,929s, repeat view: 1,072s