<?xml version="1.0" encoding="utf-8" ?>
<?xml-stylesheet href="/templates/nicosteiner/atom.css" type="text/css" ?>

<feed 
   xmlns="http://www.w3.org/2005/Atom"
   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
   xmlns:dc="http://purl.org/dc/elements/1.1/"
   xmlns:admin="http://webns.net/mvcb/"
   xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
   xmlns:wfw="http://wellformedweb.org/CommentAPI/">
    <link href="http://www.nicosteiner.de/feeds/atom.xml" rel="self" title="Nico Steiner - Frontend-Entwicklung und -Architektur" type="application/atom+xml" />
    <link href="http://www.nicosteiner.de/"                        rel="alternate"    title="Nico Steiner - Frontend-Entwicklung und -Architektur" type="text/html" />
    <link href="http://www.nicosteiner.de/rss.php?version=2.0"     rel="alternate"    title="Nico Steiner - Frontend-Entwicklung und -Architektur" type="application/rss+xml" />
    <title type="html">Nico Steiner - Frontend-Entwicklung und -Architektur</title>
    <subtitle type="html">Frontend-Technologien, Web Standards, Accessibility, SEO, Performance und Modularisierung</subtitle>
    
    <id>http://www.nicosteiner.de/</id>
    <updated>2012-02-05T00:42:26Z</updated>
    <generator uri="http://www.s9y.org/" version="1.4.1">Serendipity 1.4.1 - http://www.s9y.org/</generator>
    <dc:language>de</dc:language>

    <entry>
        <link href="http://www.nicosteiner.de/archives/286-New-SenSEO-version-is-coming.html" rel="alternate" title="New SenSEO version is coming" />
        <author>
            <name>Nico Steiner</name>
                    </author>
    
        <published>2012-02-05T00:31:56Z</published>
        <updated>2012-02-05T00:42:26Z</updated>
        <wfw:comment>http://www.nicosteiner.de/wfwcomment.php?cid=286</wfw:comment>
    
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://www.nicosteiner.de/rss.php?version=atom1.0&amp;type=comments&amp;cid=286</wfw:commentRss>
    
    
        <id>http://www.nicosteiner.de/archives/286-guid.html</id>
        <title type="html">New SenSEO version is coming</title>
        <content type="xhtml" xml:base="http://www.nicosteiner.de/">
            <div xmlns="http://www.w3.org/1999/xhtml">
                In the next days I will finish work on a completely refactored version of SenSEO.<br />
<br />
<strong>SenSEO will bootstrap</strong><br />
<br />
SenSEO will no longer integrate into Firebug but will be, what Mozilla calls, a bootstrapped add-on.<br />
<br />
<cite>Bootstrapped add-ons are a special kind of add-on that developers can choose to use instead of normal add-ons in order to allow users to install and use the add-on without needing to restart the application.</cite><br />
<br />
<strong>New features will come along</strong><br />
<br />
<ul><li>SenSEO will reopen with the last active tab.</li><li>Page load time is calculated with new <a href="https://dvcs.w3.org/hg/webperf/raw-file/tip/specs/NavigationTiming/Overview.html">HTML5 Navigation Timing API</a>.</li><li>SenSEO is taking <a href="http://support.google.com/webmasters/bin/answer.py?hl=en&answer=176035">Microdata</a> into account.</li></ul><br />
<br />
<strong>Some preview screenshots</strong><br />
<br />
<!-- s9ymdb:188 --><img class="serendipity_image_center" width="679" height="458" src="http://www.nicosteiner.de/uploads/senseo-preview-1.png" alt="SenSEO preview" /><br />
<br />
<!-- s9ymdb:189 --><img class="serendipity_image_center" width="677" height="456" src="http://www.nicosteiner.de/uploads/senseo-preview-2.png" alt="SenSEO preview" /><br />
<br />
<!-- s9ymdb:190 --><img class="serendipity_image_center" width="675" height="458" src="http://www.nicosteiner.de/uploads/senseo-preview-3.png" alt="SenSEO preview" /><br />
<br />
The refactored code in most cases is based on web technologies - don't nail me down on that, but this should make it easier to publish SenSEO on other platforms also.<br />
<br />
<img src="http://admintell.napco.com/ee/images/uploads/gamertell/chrome-firefox-fight-ie-gives-up.jpg" alt="SenSEO for Chrome"><br />
<br />
If you find bugs (there will be some, the code is brand new), please report them on <a href="http://getsatisfaction.com/senseo">getsatisfaction.com/senseo</a>. 
            </div>
        </content>
        
    </entry>
    <entry>
        <link href="http://www.nicosteiner.de/archives/285-Mini-Suchmaschine-mit-Frontend-Technologien.html" rel="alternate" title="Mini-Suchmaschine mit Frontend-Technologien" />
        <author>
            <name>Nico Steiner</name>
                    </author>
    
        <published>2011-10-24T18:44:56Z</published>
        <updated>2011-10-24T19:52:15Z</updated>
        <wfw:comment>http://www.nicosteiner.de/wfwcomment.php?cid=285</wfw:comment>
    
        <slash:comments>2</slash:comments>
        <wfw:commentRss>http://www.nicosteiner.de/rss.php?version=atom1.0&amp;type=comments&amp;cid=285</wfw:commentRss>
    
            <category scheme="http://www.nicosteiner.de/categories/3-Referenzen" label="Referenzen" term="Referenzen" />
    
        <id>http://www.nicosteiner.de/archives/285-guid.html</id>
        <title type="html">Mini-Suchmaschine mit Frontend-Technologien</title>
        <content type="xhtml" xml:base="http://www.nicosteiner.de/">
            <div xmlns="http://www.w3.org/1999/xhtml">
                Die <a href="http://www.sensational-seo.com/">SenSEO-Extension</a> bekommt ein neues Feature "Analyze all pages". Hiermit soll es möglich sein, mit einem Klick die gesamte Website zu crawlen und sämtliche Seiten anhand vorgegebener Keywords zu bewerten. Dieses Crawlen und Bewerten wird ausschließlich mit Frontend-Technologien implementiert. Die nachfolgende Grafik zeigt die geplanten Schritte.<br />
<br />
<!-- s9ymdb:187 --><img width="708" height="637" src="http://www.nicosteiner.de/uploads/mini-crawler.png" alt="Mini-Searchengine" /><br />
<br />
Der Anfang ist bereits geschafft. Mit <a href="http://www.sensational-seo.com/mini-searchengine/">diesem Prototypen</a> (läuft nur im Firefox) ist es möglich, aus dem Markup einer vorgegebenen Seite sämtliche Links zu extrahieren. Es können lediglich Seiten von sensational-seo.com angegeben werden, da die <a href="http://en.wikipedia.org/wiki/Same_origin_policy">Same Origin Policy</a> nur Seiten der selben Domain für die Analyse zulässt.<br />
<br />
Das Markup wird mit der <a href="http://www.w3.org/TR/XMLHttpRequest/ ">XMLHttpRequest API</a> abgerufen und mit der evaluate Function der Firefox <a href="https://developer.mozilla.org/en/Introduction_to_using_XPath_in_JavaScript">XPath JavaScript API</a> geparst.<br />
<br />
Da die API lediglich DOM Dokumente https://developer.mozilla.org/en/DOM/document verarbeitet, wird die als String gelieferte XMLHttpRequest Response vorher einem iFrame als Inhalt zugewiesen. Der folgende Code macht dies möglich.<br />
<br />
<pre>// create iframe<br />
var responseTextIframeElement = document.createElement('iframe');<br />
responseTextIframeElement.setAttribute('width', '0');<br />
responseTextIframeElement.setAttribute('height', '0');<br />
responseTextIframe = document.body.appendChild(responseTextIframeElement);<br />
responseTextIframe.contentWindow.document.write(responseText);<br />
var responseXML = responseTextIframe.contentWindow.document;<br />
// clear iframe<br />
responseTextIframe.parentNode.removeChild(responseTextIframe);<br />
mse.Crawler.gotPageContentByUrl(responseXML);</pre><br />
<br />
Möchte man ohne XMLHttpRequest API arbeiten, kann man einem zuvor erzeugten iFrame auch einfach den URL als scr-Attribut zuweisen.<br />
<br />
<pre>// create iframe<br />
var responseTextIframeElement = document.createElement('iframe');<br />
responseTextIframeElement.setAttribute('width', '0');<br />
responseTextIframeElement.setAttribute('height', '0');<br />
responseTextIframe = document.body.appendChild(responseTextIframeElement);<br />
responseTextIframe.addEventListener('load', function(e) {<br />
  var responseTextIframe = this;<br />
  var responseXML = responseTextIframe.contentWindow.document;<br />
  // clear iframe<br />
  responseTextIframe.parentNode.removeChild(responseTextIframe);<br />
  // this is not the best sollution<br />
  mse.Crawler.gotPageContentByUrl(responseXML);<br />
}, false);<br />
responseTextIframe.src = url;        </pre><br />
<br />
Die Extrahierung der href-Attribute aus sämtlichen Anker-Tags übernimmt dann der folgende Code.<br />
<br />
<pre>var allLinksXpath = responseXML.evaluate('/html/body//a/@href', responseXML, null, XPathResult.ANY_TYPE, null);</pre><br />
<br />
In einem nächsten Schritt sollen all die Verlinkungen extrahiert werden, welche absolut (mit http Schema) auf die selbe Domain verweisen oder Seiten relativ referenzieren. Diese Verlinkungen werden mit der <a href="http://dev.w3.org/html5/webstorage/">Local Storage API</a> auf einem Stack abgelegt und sequentiell nach dem LILO-Prinzip (Last in, Last out) gecrawlt. Dabei wird die Bereinigung von Dubletten mit Hilfe des <a href="http://googlewebmastercentral.blogspot.com/2009/02/specify-your-canonical.html">Canonical-Tag</a> eine wichtige Rolle spielen. Im Local Storage wird neben der extrahierten URL also auch immer eine zweite kanonische URL abgelegt, welche durch einen entsprechenden Abgleich das doppelte Crawlen von Seiten verhindern soll. 
            </div>
        </content>
        
    </entry>
    <entry>
        <link href="http://www.nicosteiner.de/archives/284-Rendern-von-Seiten-Komponenten.html" rel="alternate" title="Rendern von Seiten-Komponenten" />
        <author>
            <name>Nico Steiner</name>
                    </author>
    
        <published>2011-08-01T19:55:54Z</published>
        <updated>2011-08-02T06:59:37Z</updated>
        <wfw:comment>http://www.nicosteiner.de/wfwcomment.php?cid=284</wfw:comment>
    
        <slash:comments>1</slash:comments>
        <wfw:commentRss>http://www.nicosteiner.de/rss.php?version=atom1.0&amp;type=comments&amp;cid=284</wfw:commentRss>
    
    
        <id>http://www.nicosteiner.de/archives/284-guid.html</id>
        <title type="html">Rendern von Seiten-Komponenten</title>
        <content type="xhtml" xml:base="http://www.nicosteiner.de/">
            <div xmlns="http://www.w3.org/1999/xhtml">
                Möchte man nur Teile einer Seite neu rendern, ohne den Rest der Seite zu verändern, bedient man sich häufig der DOM-Manipulation mit JavaScript. Sind an diesem Prozess dynamische Daten beteiligt, die auf dem Server gehalten werden, kommt auch noch XHR und JSON zum Austausch der Daten hinzu. Konkret ergeben sich daraus folgende Schritte, die für gewöhnlich als AJAX bezeichnet werden:<br />
<br />
<ol><li>Ein XHR-Request erfragt Daten vom Server, die dieser in einer Session hält</li><li>Der Server sendet die angeforderten Daten im JSON-Format und der Client wandelt diese in JavaScript-Objekte</li><li>Basierend auf den so entstandenen Objekten werden mit JavaScript Manipulationen am bestehenden HTML-Dokument vorgenommen</li></ol><br />
<br />
<strong>Einige Nachteile dieses Vorgehens</strong><br />
<br />
<ul><li>Der Ansatz funktioniert nur mit JavaScript - ohne JavaScript findet keine Veränderung des Dokuments statt</li><li>Eigens für die DOM-Manipulation muss JavaScript-Code geschrieben werden - auf eventuell bestehenden Code des Templatesystems auf dem Server kann nicht zurückgegriffen werden</li><li>Durch Punkt 2 besteht die Tendenz zum Duplizieren von Code in verschiedenen Sprachen auf Server- und Clientseite</li><li>Setzt man sehr massiv auf den oben beschriebenen Ansatz, sind für Suchmaschinen kaum verwertbare Inhalte verfügbar</li></ul><br />
<br />
<strong>Wie können diese Nachteile umgangen werden?</strong><br />
<br />
Die meisten Templatesysteme setzen das HTML-Dokument aus einer Kombination verschiedener Seiten-Komponenten zusammen - typisch hierfür sind ein Header-, Content- und Footer-Bereich - aber auch Navigation, Sidebar etc. bilden solche Komponenten. Oft werden dynamische Daten genutzt, um z. B. eine Navigation zu erzeugen, die Links zu neu erzeugten Seiten generiert, ohne weitere Veränderungen am Code vorzunehmen zu müssen.<br />
<br />
Am Beispiel einer Kostenübersicht möchte ich demonstrieren, wie solch eine Komponente mit XHR nach jeder Veränderung des Warenkorbs ohne Neuladen der Seite aktualisiert werden kann. Der folgende Wireframe zeigt den schematisch Aufbau der Seite - links die zu aktualisierende Kostenübersicht, rechts der Bereich, über den Veränderungen am Warenkorb vorgenommen werden können.<br />
<br />
<div style="text-align: center;"><!-- s9ymdb:184 --><img class="serendipity_image_center" width="500" height="425" style="border: 0px; margin: 0 auto;" src="http://www.nicosteiner.de/uploads/telesales-1.png" alt="Beispiel für eine Kostenübersicht" /></div><br />
<br />
<strong>Schritt 1 - Der initial Request</strong><br />
<br />
Der initiale Request ruft die Seite das erste Mal vom Server ab. Angenommen, es befinden sich zu diesem Zeitpunkt bereits zwei Artikel im Warenkorb, dann würde die Kostenübersicht von einer Komponente erzeugt werden, die für jeden der zwei Artikel eine neue Tabellenzeile mit den zugehörigen Daten generiert. Zusammen mit den übrigen Teilen der Seite entsteht ein komplettes HTML-Dokument, welches über HTTP an den Browser ausgeliefert wird.<br />
<br />
<div style="text-align: center;"><!-- s9ymdb:185 --><img class="serendipity_image_center" width="453" height="553" style="border: 0px; margin: 0 auto;" src="http://www.nicosteiner.de/uploads/html-xslt.png" alt="Initialer HTTP-Request" /></div><br />
<br />
Soweit ist dies der klassische Ansatz, wie er von den meisten Frameworks verfolgt wird.<br />
<br />
<strong>Schritt 2 - Ein Artikel wird hinzugefügt</strong><br />
<br />
Für das hinzufügen eines Artikels existiert ein Anker-Tag, welches einem Server-Script den neuen Artikel als GET-Paramter übergibt. Um das Neuladen der Seite zu verhindern, wird das Verhalten des Anker-Tags mit JavaScript unterbunden und statt dessen der Artikel über einen Webservice-Call mit XHR an den Server kommuniziert. Somit haben wir ein korrektes Verhalten für aktiviertes und deaktivertes JavaScript sichergestellt.<br />
<br />
In beiden Fällen wird dem Warenkorbsystem auf dem Server der ausgewählte Artikel hinzugefügt. Bei deaktiviertem JavaScript würde erneut ein HTML-Dokument mit dem neuen Artikel in der Kostenübersicht erzeugt und über HTTP an den Browser ausgeliefert werden. Das interessante Verhalten ergibt sich bei aktiviertem JavaScript. Nachdem der Webserivce-Call erfolgreich verarbeitet wurde, gilt es die Kostenübersicht zu aktualisieren. Beim klassischen AJAX-Ansatz würde die Response die neuen Warenkorb-Artikel enthalten und per DOM-Manipulation würde die Tabelle der Kostenübersicht um eine weitere Zeile ergänzt werden. Dies kann bei komplexeren Problemen schnell sehr aufwändig werden. Eine elegantere Lösung besteht darin, das HTML-Fragment der Kostenübersicht auf dem Server neu erzeugen zu lassen und anschließend das bestehende Fragment mit JavaScript durch das neu erzeugte zu ersetzten. Die folgende Grafik soll diese Lösung veranschaulichen.<br />
<br />
<div style="text-align: center;"><!-- s9ymdb:186 --><img class="serendipity_image_center" width="500" height="318" style="border: 0px; margin: 0 auto;" src="http://www.nicosteiner.de/uploads/html-xslt-2.png" alt="Schaubild für HTML-Fragment" /></div><br />
<br />
<strong>Welche Probleme gibt es hierbei zu lösen</strong><br />
<br />
Es muss eine Verbindung vom alten zum neuen HTML-Fragment hergestellt werden können. Am einfachsten ist dies mit einer Element-ID möglich, über welche das Fragment identifiziert und durch das neue ersetzt werden kann. Weiterhin muss das serverseitige Templatesystem/Framework eine entsprechende Funktionalität zum selektiven Neurendern von Seitenkomponenten bereitstellen. Komponentenbasierte Frameworks bieten hier die besten Chancen für einen solchen Support. Eine weitere Herausforderung stellt das Erzeugen und Entfernen von Event-Listenern auf Elemente des Fragments dar - auch hier sollte das Framework eine entsprechende Unterstützung bieten. 
            </div>
        </content>
        
    </entry>
    <entry>
        <link href="http://www.nicosteiner.de/archives/283-Huehnersuppe-ala-Mama.html" rel="alternate" title="Hühnersuppe ala Mama" />
        <author>
            <name>Nico Steiner</name>
                    </author>
    
        <published>2011-08-01T16:07:30Z</published>
        <updated>2011-08-01T16:48:11Z</updated>
        <wfw:comment>http://www.nicosteiner.de/wfwcomment.php?cid=283</wfw:comment>
    
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://www.nicosteiner.de/rss.php?version=atom1.0&amp;type=comments&amp;cid=283</wfw:commentRss>
    
            <category scheme="http://www.nicosteiner.de/categories/6-Rezepte" label="Rezepte" term="Rezepte" />
    
        <id>http://www.nicosteiner.de/archives/283-guid.html</id>
        <title type="html">Hühnersuppe ala Mama</title>
        <content type="xhtml" xml:base="http://www.nicosteiner.de/">
            <div xmlns="http://www.w3.org/1999/xhtml">
                Bei Erkältung hilft nur eins - die Hühnersuppe ala Mama. Die Zubereitung ist einfach und der <a href="http://www.zeit.de/2003/11/Stimmts_H_9fhnersuppe" title="Suppentherapie Zeit-Online">Erkältung fällt dann auch nix mehr ein</a>.<br />
<br />
Folgende Zutaten werden für eine große Portion Hühnersuppe benötigt (bei einer kleineren Portion die halbe Menge oder fertig abgepacktes Suppengemüse kaufen):<br />
<br />
<!-- s9ymdb:182 --><img width="300" height="225" style="float: right; border: 0px; padding-left: 5px;" src="http://www.nicosteiner.de/uploads/huehnersuppe1.jpg" alt="Hühnersuppe ala Mama" /><ul><li>1 großes Suppenhuhn vom Markt oder aus dem BIO-Laden</li><li>250g Suppennudeln</li><li>1 Kohlrabi</li><li>1 Butterrübe</li><li>1 Knolle Sellerie</li><li>2 mittelgroße Möhren</li><li>1 Stange Lauch</li><li>1 Bund Petersilie</li><li>Salz</li><li>Gemahlener schwarzer Pfeffer</li></ul><br />
<br />
Das Huhn ggf. auftauen und dann mit viel Wasser und reichlich Salz in einem großen Topf bei halb aufgelegtem Deckel zum Kochen bringen. Danach auf mittlere Hitze zurückschalten und weiter kochen lassen.<br />
<br />
Das Gemüse schälen und grob in größere Stücke zerteilen. Das Kleinschneiden kommt später. Beim Lauch gibt es zu beachten, dass auch die oberen, grünen Teile mitgekocht werden. Die Gemüsestücke zum Huhn in den Topf geben und ca. 20-30 Minuten gar kochen. Danach mit einer Schöpfkelle wieder aus dem Topf fischen (das Huhn kocht weiter), in eine Schüssel geben, klein schneiden und beiseite stellen. Je nach Geschmack nicht das gesamte Gemüse kleingeschneiden - von der Menge her ist das eher zu viel.<br />
<br />
Wenn das Huhn nach 1-2 Stunden gar gekocht ist (das Fleisch sollte sich ganz leicht vom Knochen lösen lassen) aus dem Topf nehmen, die Haut und die Knochen entfernen und das Hühnerfleisch in kleine Stücke schneiden. Parallel dazu Wasser mit einer Prise Salz in einem separaten Topf zum Kochen bringen und die Suppennudeln darin nach Anleitung kochen. Die Nudeln danach in ein feinmaschiges Sieb abgießen und zusammen mit den Fleischstücken und dem geschnitten Gemüse zurück in den Topf geben.<br />
<br />
Die Suppe mit Salz und Pfeffer abschmecken. Zum Schluss die Petersilie mit einem Wiegemesser klein schneiden und über die fertige Suppe streuen.<br />
<br />
<strong>Ein paar Tipps</strong><br />
<br />
Suppe braucht viel Salz. Wenn trotzdem mal zu viel Salz an die Suppe gerät, hilft es, eine Kartoffel mitzukochen. Diese saugt das Salz auf und kann später weggeworfen werden.<br />
<br />
Wer die Suppe nicht ganz so fett mag, kann sie auch erst erkalten lassen, dann in den Kühlschrank stellen und nach einigen Stunden die Schicht Fett abziehen, die sich auf der Suppe bildet.<br />
<br />
Hühnersuppe läßt sich prima einfrieren. Größere Mengen am besten in Portionen aufteilen, da jedes erneute Aufkochen den Nudeln schadet. 
            </div>
        </content>
        
    </entry>
    <entry>
        <link href="http://www.nicosteiner.de/archives/282-SenSEO-Infografik.html" rel="alternate" title="SenSEO Infografik" />
        <author>
            <name>Nico Steiner</name>
                    </author>
    
        <published>2011-04-05T15:33:21Z</published>
        <updated>2011-04-05T15:33:21Z</updated>
        <wfw:comment>http://www.nicosteiner.de/wfwcomment.php?cid=282</wfw:comment>
    
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://www.nicosteiner.de/rss.php?version=atom1.0&amp;type=comments&amp;cid=282</wfw:commentRss>
    
    
        <id>http://www.nicosteiner.de/archives/282-guid.html</id>
        <title type="html">SenSEO Infografik</title>
        <content type="xhtml" xml:base="http://www.nicosteiner.de/">
            <div xmlns="http://www.w3.org/1999/xhtml">
                Zum 200.000sten Download von SenSEO habe ich als kleines Dankeschön eine Infografik mit interessanten Fakten zur Firefox-Extension zusammengestellt.<br />
<br />
<!-- s9ymdb:181 --><img class="serendipity_image_center" width="725" height="575" src="http://www.nicosteiner.de/uploads/senseo-infographic.png" alt="SenSEO Infografik" /> 
            </div>
        </content>
        
    </entry>
    <entry>
        <link href="http://www.nicosteiner.de/archives/281-Gastartikel-im-Webstandard-Blog.html" rel="alternate" title="Gastartikel im Webstandard-Blog" />
        <author>
            <name>Nico Steiner</name>
                    </author>
    
        <published>2010-10-19T14:50:43Z</published>
        <updated>2010-10-19T14:56:49Z</updated>
        <wfw:comment>http://www.nicosteiner.de/wfwcomment.php?cid=281</wfw:comment>
    
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://www.nicosteiner.de/rss.php?version=atom1.0&amp;type=comments&amp;cid=281</wfw:commentRss>
    
            <category scheme="http://www.nicosteiner.de/categories/3-Referenzen" label="Referenzen" term="Referenzen" />
    
        <id>http://www.nicosteiner.de/archives/281-guid.html</id>
        <title type="html">Gastartikel im Webstandard-Blog</title>
        <content type="xhtml" xml:base="http://www.nicosteiner.de/">
            <div xmlns="http://www.w3.org/1999/xhtml">
                Gestern erschien im <a href="http://webstandard.kulando.de/">Webstandard-Blog</a> der erste von 3 Artikeln zur Verbesserung der Website-Performance mit Expires-Headern. Die Artikel basieren auf <a href="http://stevesouders.com/hpws/">Steve Souders Veröffentlichungen</a> und den praktischen Erfahrungen, die ich mit dem <a href="http://www.nicosteiner.de/archives/275-Content-Delivery-Server-online!.html">Content Delivery Server</a> gesammelt habe. Der zweite und dritte Teil folgen die nächsten Tage. 
            </div>
        </content>
        
    </entry>
    <entry>
        <link href="http://www.nicosteiner.de/archives/280-CSS3-Redesign-abgeschlossen.html" rel="alternate" title="CSS3 Redesign abgeschlossen" />
        <author>
            <name>Nico Steiner</name>
                    </author>
    
        <published>2010-10-17T11:59:03Z</published>
        <updated>2010-10-17T11:59:03Z</updated>
        <wfw:comment>http://www.nicosteiner.de/wfwcomment.php?cid=280</wfw:comment>
    
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://www.nicosteiner.de/rss.php?version=atom1.0&amp;type=comments&amp;cid=280</wfw:commentRss>
    
    
        <id>http://www.nicosteiner.de/archives/280-guid.html</id>
        <title type="html">CSS3 Redesign abgeschlossen</title>
        <content type="xhtml" xml:base="http://www.nicosteiner.de/">
            <div xmlns="http://www.w3.org/1999/xhtml">
                So - jetzt bin ich zufrieden. Ohne eine Zeile HTML zu ändern und mit vielen neuen CSS3 Regeln hat das Blog einen neuen Look bekommen. Das Redesign war ein Versuch, dass Wissen aus <a href="http://fronteers.nl/congres/2010/workshops/css3-dan-rubin">Dan Rubins CSS3 Workshop</a> praktisch anzuwenden.  
            </div>
        </content>
        
    </entry>
    <entry>
        <link href="http://www.nicosteiner.de/archives/279-Halb-zwei-uff....html" rel="alternate" title="Halb zwei - uff..." />
        <author>
            <name>Nico Steiner</name>
                    </author>
    
        <published>2010-10-15T23:28:52Z</published>
        <updated>2010-10-15T23:29:58Z</updated>
        <wfw:comment>http://www.nicosteiner.de/wfwcomment.php?cid=279</wfw:comment>
    
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://www.nicosteiner.de/rss.php?version=atom1.0&amp;type=comments&amp;cid=279</wfw:commentRss>
    
            <category scheme="http://www.nicosteiner.de/categories/4-Privat" label="Privat" term="Privat" />
    
        <id>http://www.nicosteiner.de/archives/279-guid.html</id>
        <title type="html">Halb zwei - uff...</title>
        <content type="xhtml" xml:base="http://www.nicosteiner.de/">
            <div xmlns="http://www.w3.org/1999/xhtml">
                Bin immer noch nicht zufrieden, gehe jetzt aber erstmal ins Bett. 
            </div>
        </content>
        
    </entry>
    <entry>
        <link href="http://www.nicosteiner.de/archives/278-CSS3-Redesign-startet-jetzt.html" rel="alternate" title="CSS3 Redesign startet jetzt" />
        <author>
            <name>Nico Steiner</name>
                    </author>
    
        <published>2010-10-15T19:58:29Z</published>
        <updated>2010-10-15T19:58:29Z</updated>
        <wfw:comment>http://www.nicosteiner.de/wfwcomment.php?cid=278</wfw:comment>
    
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://www.nicosteiner.de/rss.php?version=atom1.0&amp;type=comments&amp;cid=278</wfw:commentRss>
    
            <category scheme="http://www.nicosteiner.de/categories/4-Privat" label="Privat" term="Privat" />
    
        <id>http://www.nicosteiner.de/archives/278-guid.html</id>
        <title type="html">CSS3 Redesign startet jetzt</title>
        <content type="xhtml" xml:base="http://www.nicosteiner.de/">
            <div xmlns="http://www.w3.org/1999/xhtml">
                Für die nächsten Stunden wird die Seite übel aussehen - danach hoffentlich nicht mehr... <img src="http://www.nicosteiner.de/templates/nicosteiner/img/emoticons/wink.png" alt=";-)" style="display: inline; vertical-align: bottom;" class="emoticon" /> 
            </div>
        </content>
        
    </entry>
    <entry>
        <link href="http://www.nicosteiner.de/archives/277-Vortrag-auf-der-WebTechCon-2010.html" rel="alternate" title="Vortrag auf der WebTechCon 2010" />
        <author>
            <name>Nico Steiner</name>
                    </author>
    
        <published>2010-10-13T21:49:22Z</published>
        <updated>2010-10-13T22:25:02Z</updated>
        <wfw:comment>http://www.nicosteiner.de/wfwcomment.php?cid=277</wfw:comment>
    
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://www.nicosteiner.de/rss.php?version=atom1.0&amp;type=comments&amp;cid=277</wfw:commentRss>
    
            <category scheme="http://www.nicosteiner.de/categories/3-Referenzen" label="Referenzen" term="Referenzen" />
    
        <id>http://www.nicosteiner.de/archives/277-guid.html</id>
        <title type="html">Vortrag auf der WebTechCon 2010</title>
        <content type="xhtml" xml:base="http://www.nicosteiner.de/">
            <div xmlns="http://www.w3.org/1999/xhtml">
                Ich bin wieder zurück von der <a href="http://webtechcon.de/2010/timetable">WebTechCon 2010</a>. Neben einigen interessanten Vorträgen und jeder Menge Socializing habe auch ich einen Vortrag gehalten. Es ging um die Frontend-Architektur unserer Abteilung.<br />
<br />
<a href="http://www.slideshare.net/n.steiner/frontendarchitektur-der-11-bestellsysteme">"Frontend-Architektur der 1&1 Bestellsysteme" bei Slideshare</a><br />
<br />
Es gab einige interessante Fragen und jede Menge positives Feedback (<a href="http://twitter.com/netzartist/status/27242713492">zwitscher</a>, <a href="http://twitter.com/mac3uck/status/27241244239">zwitscher</a>, <a href="http://twitter.com/trishi_de/status/27244746057">zwitscher</a>).<br />
<br />
Einige Dinge, die ich aus den Gesprächen mitnehme:<br />
<br />
</p><ul><li>Viele Entwickler sitzen auf zwei Stühlen - PHP und das bißchen Frontend gleich noch mit. Den meisten ist bewußt, dass das alles andere als optimal ist</li><li>Sehr gewachsene, heterogene Infrastrukturen - Konsolidierung nicht in Sicht (Zeit- oder Geldmangel)</li><li>Uneinsichtige Chefs blockieren Innovationen</li><li>Gute Kollegen trösten über vieles hinweg</li><li>Kicker sind Mangelware</li><li>Großraumbüros sind definitiv keine Option für Entwickler</li></ul><p>Das macht mir mal wieder deutlich klar, wie gut wir eigentlich mit Personal und Systemen aufgestellt sind und wie viel Nachholbedarf andere Firmen da noch haben.<br />
<br />
Letzte Woche war ich zusammen mit Andi und Mathias auf der Fronteers in Amsterdam. Chris Heilmann hat die Talks der Konferenz <a href="http://www.wait-till-i.com/2010/10/10/fronteers-2010-report-and-my-slides-and-links/">sehr gut zusammengefasst</a>. Bleibt nur noch hinzuzufügen, dass der CSS3 Workshop von Dan Rubin sehr lehrreich und kurzweilig war. 
            </div>
        </content>
        
    </entry>
    <entry>
        <link href="http://www.nicosteiner.de/archives/276-Die-Webseite.html" rel="alternate" title="Die Webseite" />
        <author>
            <name>Nico Steiner</name>
                    </author>
    
        <published>2010-10-02T13:06:06Z</published>
        <updated>2010-10-09T19:24:10Z</updated>
        <wfw:comment>http://www.nicosteiner.de/wfwcomment.php?cid=276</wfw:comment>
    
        <slash:comments>2</slash:comments>
        <wfw:commentRss>http://www.nicosteiner.de/rss.php?version=atom1.0&amp;type=comments&amp;cid=276</wfw:commentRss>
    
            <category scheme="http://www.nicosteiner.de/categories/4-Privat" label="Privat" term="Privat" />
    
        <id>http://www.nicosteiner.de/archives/276-guid.html</id>
        <title type="html">Die Webseite</title>
        <content type="xhtml" xml:base="http://www.nicosteiner.de/">
            <div xmlns="http://www.w3.org/1999/xhtml">
                Inspiriert durch dieses <a href="http://www.youtube.com/watch?v=mRggWhM70Wc">Meisterwerk von Jochen Malmsheimer</a> (unbedingt vorher ansehen, sonst kommt der Witz nicht rüber) habe ich versucht, diesen Gag auf ein anderes Thema zu übertragen. <br />
<br />
<strong>Die Webseite</strong><br />
<br />
Wie geht eine Webseite? Fangen wir unten an. Da ist das valides HTML. VALIDES HTML! Mit einer richtigen Semantik, damit die Elemente der Seite auch eine anständige Bedeutung haben. Richtiges HTML, semantisch, suchmaschinenoptimiert. Nicht diese zusammengeschusterte Tagsuppe, die ihr Layout in Tabellen presst und von Headlines noch nie etwas gehört hat!<br />
<br />
Da drauf - extern, minimiert und komprimiert - <a href="http://www.slideshare.net/stubbornella/object-oriented-css">gutes CSS</a>! Man kann auch Stylesheets oder Layout dazu sagen. Und das CSS rendert von oben über das HTML, und dann lernen sie sich kennen und dann tun sie sich zusammen - denn sie wissen, gleich gibt's noch richtig was auf's Dach.<br />
<br />
Und dann! Das ist jetzt ganz wichtig, Zettel raus, Stifte und mitschreiben - BITTE! Und dann...! <a href="http://www.onlinetools.org/articles/unobtrusivejavascript/">Unobtrusive</a>, buchstabiert U-N-O-B-T-R-U-S-I-V-E, JavaScript! Die Zeiten von Inline-Events sind vorbei!<br />
<br />
Die müssen sauber voneinander getrennt sein! HTML und CSS bilden Gerüst und Layout der Seite und JavaScript fügt eine Logik-Schicht hinzu. Und dann gibt das eine Technologieexplosion, die einem die Zähne aus dem Hals bläst, wenn sie nicht ordentlich verschraubt sind!<br />
<br />
DAS IST GUT! Seit Jahren ist das so gut! Das sind Webstandards!<br />
<br />
Bis... zu diesem furchtbaren Tag... an dem so ein mental verotteter Grafiker (sorry, Jungs) DA FLASH DRAUFGEMACHT HAT, UND GRAFISCHE HEADLINES, UND VERLÄUFE UND OHNE ENDE SCHLAGSCHATTEN! DU HAST DAS GEFÜHL, DU BLICKST AUF EINE SCHIESSBUDE! DAS HAT DOCH MIT EINER WEBSEITE NICHTS ZU TUN! ICH WERDE NOCH WAHNSINNIG!<br />
<br />
ICH... ich bin für den Einsatz des Militärs im eigenen Land! Die Soldaten sollen die Grafiker unter vorgehaltener Waffe dazu zwingen, ihre eigenen Webseiten mit einem Screenreader zu bedienen! Ein Grafiker soll morgens ins Büro kommen, eine anständige Webseite layouten und wieder nach Hause gehen - ist das denn so schwer ?!?<br />
<br />
Das mache ich fast jeden Tag - könnt ihr euch das vorstellen? Das ich das gesundheitlich überhaupt mitmache! Auf der anderen Seite finde ich, dass ein so durchaus technologielastiges Blog wie dieses so einen Hauch von Emotion durchaus verträgt. Auf der anderen Seite fragt sich der eine oder andere Leser diese Artikels jetzt vielleicht... Was - hat - der - Mann?<br />
<br />
<strong>RECHT HAT ER!!!</strong><br />
<br />
Danke an Andi und Matthias, die zum Teil unter dem Einsatz alkoholischer Getränke ihren Beitrag geleistet haben <img src="http://www.nicosteiner.de/templates/nicosteiner/img/emoticons/smile.png" alt=":-)" style="display: inline; vertical-align: bottom;" class="emoticon" /> 
            </div>
        </content>
        
    </entry>
    <entry>
        <link href="http://www.nicosteiner.de/archives/275-Content-Delivery-Server-online!.html" rel="alternate" title="Content Delivery Server online!" />
        <author>
            <name>Nico Steiner</name>
                    </author>
    
        <published>2010-09-30T15:21:54Z</published>
        <updated>2010-09-30T19:01:46Z</updated>
        <wfw:comment>http://www.nicosteiner.de/wfwcomment.php?cid=275</wfw:comment>
    
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://www.nicosteiner.de/rss.php?version=atom1.0&amp;type=comments&amp;cid=275</wfw:commentRss>
    
            <category scheme="http://www.nicosteiner.de/categories/3-Referenzen" label="Referenzen" term="Referenzen" />
    
        <id>http://www.nicosteiner.de/archives/275-guid.html</id>
        <title type="html">Content Delivery Server online!</title>
        <content type="xhtml" xml:base="http://www.nicosteiner.de/">
            <div xmlns="http://www.w3.org/1999/xhtml">
                Seit gestern werden auf der <a href="http://www.united-internet.de">United Internet AG Website</a> sämtliche Grafiken über einen Content Delivery Server ausgeliefert. Dieser komplettiert das Puzzle an Optimierungen, welches die Performance unserer Shops verbessern soll.<br />
<br />
Folgende Features wurden in der ersten Phase implementiert:<br />
<br />
- Far Future Expires Header (<a href="http://developer.yahoo.com/performance/rules.html#expires">mehr Infos bei Yahoo!</a>)<br />
- Umschreiben der Grafikpfade auf eine Hashtag-Version<br />
- Cookiefreie Domain (<a href="http://developer.yahoo.com/performance/rules.html#cookie_free">mehr Infos bei Yahoo!</a>)<br />
- Mehr parallele Downloads dank verschiedener Subdomains (<a href="http://developer.yahoo.com/performance/rules.html#split">mehr Infos bei Yahoo!</a>)<br />
<br />
Zum zweiten Feature habe ich keine gute Quelle im Netz gefunden. Es geht hierbei um das Problem, dass eine Grafik mit Expires Header ohne Conditional GET aus dem Cache geladen wird. Was prinzipiell erwünscht ist wird zu einem Problem, wenn eine veränderte Version dieser Grafik gepublished wird. Um dann trotzt des Expires Headers ein Neuladen zu erzwingen, ist eine veränderte Grafik-URL nötig. Für gewöhnlich kann man sich zwischen einer Versionierung und einem Hash Tag entscheiden. Letzteres erschien uns praktikabler, da ein Hash Tag vergleichsweise einfach implementiert werden kann. Facebook hat das gleiche Verfahren gewählt, Amazon dagegen setzt auf eine Versionierung der Dateinamen.<br />
<br />
Eine Vorher-Nachher-Analyse belegt die Verbesserungen eindrucksvoll. Obwohl auf der Website vergleichsweise wenige Grafiken eingebunden werden, werden die Seiten beim 1. Request (dank 8 statt 2 parallelen Downloads) 25% schneller geladen. Beim 2. Request ist dank des optimalen Cache-Verhaltens eine Zeiteinsparung von fast 40% messbar. Es gibt diverse Studien, die eine verbesserte User Experience durch schnelle Ladezeiten belegen. Beispielhaft sei auf einige <a href="http://www.webperformancetoday.com/2010/07/01/the-best-graphs-of-velocity/">Statistiken der letzten Velocity</a> verwiesen.<br />
<br />
Im Verlauf der nächsten Monate werden wir den CDS in die sehr viel grafiklastigeren Shops integrieren und die Verbesserungen in diesem Umfeld dokumentieren. Man darf gespannt sein.<br />
<br />
Für die Zukunft sind weitere Features geplant. So soll mit den Daten des CDS ein "selbstlernendes" <a href="http://www.4thkingdom.com/public/computers/789073-web-site-speed-prefetching-images-css/view-post.html">Image Prefetching</a> gebaut werden. In einem weiteren Schritt könnte der CDS zu einem <a href="http://developer.yahoo.com/performance/rules.html#cdn">Content Delivery Network</a> ausgebaut werden, um statische Ressourcen weltweit mit möglichst geringer Latenz auszuliefern.<br />
<br />
Darauf <a href="http://www.myvideo.de/watch/4862326/Seeed_Oceans_11">hoch die Tassen</a>! 
            </div>
        </content>
        
    </entry>
    <entry>
        <link href="http://www.nicosteiner.de/archives/191-11-DSL-Performance-Optimierungen.html" rel="alternate" title="1&amp;1 DSL - Performance-Optimierungen" />
        <author>
            <name>Nico Steiner</name>
                    </author>
    
        <published>2009-10-18T10:10:13Z</published>
        <updated>2010-09-30T19:01:43Z</updated>
        <wfw:comment>http://www.nicosteiner.de/wfwcomment.php?cid=191</wfw:comment>
    
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://www.nicosteiner.de/rss.php?version=atom1.0&amp;type=comments&amp;cid=191</wfw:commentRss>
    
            <category scheme="http://www.nicosteiner.de/categories/3-Referenzen" label="Referenzen" term="Referenzen" />
    
        <id>http://www.nicosteiner.de/archives/191-guid.html</id>
        <title type="html">1&amp;1 DSL - Performance-Optimierungen</title>
        <content type="xhtml" xml:base="http://www.nicosteiner.de/">
            <div xmlns="http://www.w3.org/1999/xhtml">
                Das DSL-Projekt ging letzte Woche mit dem neuen <a href="http://www.nicosteiner.de/archives/185-Neue-Jasmin-Servlet-Version.html" title="Neue Jasmin-Servlet Version">Jasmin-Servlet 2.1</a> online. An diesem Beispiel möchte ich zeigen, wie eine weitere Optimierung dieses Projekts aussehen könnte.<br />
<br />
<strong>Der erste Request</strong><br />
<br />
In der nachfolgenden Grafik sind sämtliche Requests in Form ihrer Bestandteile, Downloadzeiten und Latenzen beim ersten Aufruf der DSL-Startseite zu sehen. Die Latenzen werden dabei von der Software simuliert, stimmen aber in ihren Relationen zueinander.<br />
<br />
<!-- s9ymdb:2 --><img class="serendipity_image_center" width="770" height="533" src="http://www.nicosteiner.de/uploads/test-first-request.png" alt="Der erste Request" /><br />
<br />
Gleich die ersten Requests (1) wären Kandidaten für eine Optimierung. Das Pustefix-Framework macht ihr diverse Redirects, bevor es die eigentlichen Inhalte ausliefert. Ideal wäre natürlich wenn dies bereits mit dem ersten Request geschehen würde. Somit könnte die Zeit bis zum ersten Rendern der Seite (die grüne, vertikale Linie) deutlich verkürzt werden. Auch die mit (2) gekennzeichneten Requests beeinflussen den Zeitpunkt des ersten Renderns negativ. Diese Requests fordern die Stylesheets des Dokuments an. Die Platzierung der Requests ist optimal, je eher die Stylesheets geladen werden, desto besser. Allerdings ist die Größe der Daten ein Problem. Dies beeinflußt nicht nur die Downloadzeit sondern auch die Zeit der Interpretation der Stylesheets (3). Insgesamt dauert es in dieser Simulation mehr als eine Sekunde, diesen Prozess abzuschließen. Das ist immerhin 1/7 der Zeit, die der Browser mit der kompletten Darstellung des Dokuments beschäftigt ist. Zukünftig wird es dank des <a href="http://creatified.com/blog/2009/06/introducing-jacqueline-unused-css-selectors-in-java/" title="Jacqueline">PMT</a> möglich sein, diverse veraltete Selektoren aus den Stylesheets zu entfernen, was an dieser Stelle eine deutliche Verbesserung bringen sollte.<br />
<br />
Im Anschluß an die Stylesheets werden die Grafiken der Startseite angefordert. Hier lassen sich für den ersten Request kaum Optimierungen finden. Eventuell sind einige weitere Hintergrundgrafiken Kandidaten für CSS-Sprites.<br />
<br />
Interessant wird es wieder bei den JavaScript-Requests (4). Auch hier wird deutlich, dass der Umfang der Scripte recht groß ist, was wiederum zusätzlich zu einer Verzögerung bei der Interpretation des JavaScript-Codes (5) führt. Hier werden wir in Zukunft auf eine asynchrones Laden der Scripte mit einem Managed XHR setzen. Wem das nichts sagt, dem sei das Buch <a href="http://oreilly.com/catalog/9780596522315" title="O'Reilly">Even Faster Web Sites</a> von Steve Souders empfohlen. Den Teil zum asynchronen Laden von JavaScript finde ich in diesem Buch neben den JavaScript-Code-Optimierungen am interessantesten.<br />
<br />
Den Abschluß bilden jede Menge Tracking-Pixel-Requests. Diese stellen eine Besondere herausforderung dar, da sie nicht Teil der eigenen Infrastruktuer sind, sondern oftmals von fremden Servern, mit all den Nachteilen die so etwas hat, bezogen werden. Gerade heute morgen hatte ich eine Idee, wie wir dieses Problem mit einer zentralisierten Lösung für solche Requests in den Griff bekommen könnten - mal sehen, was mein Chef dazu meint <img src="http://www.nicosteiner.de/templates/nicosteiner/img/emoticons/smile.png" alt=":-)" style="display: inline; vertical-align: bottom;" class="emoticon" /><br />
<br />
<strong>Der zweite Request</strong><br />
<br />
Dieser Request wird maßgeblich davon beeinflußt, dass der Browser bestimmte Daten bereits im Cache zwischengespeichert hat. Nur unter gewissen Umständen fordert dieser Daten erneut vom Server an.<br />
<br />
<!-- s9ymdb:3 --><img class="serendipity_image_center" width="770" height="450" src="http://www.nicosteiner.de/uploads/test-second-request.png" alt="Der zweite Request" /><br />
<br />
Hier wirken sich die Redirects bis zur Auslieferung des HTML-Codes (1) in Relation noch massiver aus. Ein wesentlicher Teil der zeit bis zum ersten Rendern der Seite wird dafür beansprucht.<br />
<br />
Ein viel größeres Problem wird durch die Bereiche (2), (3) und (4) sichtbar. Diese Bereich stellen sogeannte Conditional GET-Requests dar. Dabei wird beim Server erfragt, ob sich die bereits beim ersten Request abgerufenen Daten in der Zwischenzeit verändert haben. Bei den hier dargestellten Daten handelt es sich ausschließlich um Grafiken. Da sich das System, welches Grafiken zentral ausliefert und diese nur bei Veränderungen entsprechend neu versioniert, noch in der Planung befindet, müssen wir mit diesem Problem leider noch eine Weile leben. (<strong>Nachtrag:</strong> Der <a href="http://www.nicosteiner.de/archives/275-Content-Delivery-Server-online!.html">Content Delivery Server</a> ist mittlerweile fertig implementiert.)<br />
<br />
Als Fazit kann man sagen, dass wir mit unseren bisherigen Bemühungen schon große Schritte in Richtung eines performanten Frontends gegangen sind. Die hier beschriebenen Ansätze werden noch einmal eine deutliche Verbesserung bringen. Mit dem Ende dieser zweiten Phase wird das Thema Performance-Optimierung architektonisch abgehakt sein. Natürlich müssen wir während des Entwicklungsprozess bestehender und neuer Projekte darauf achten, Optimierungen am JavaScript-Code und an dem Umfang der ausgelieferten Ressourcen nicht aus dem Auge zu verlieren und als kontinuierlichen Teil unserer Arbeit zu sehen.<br />
<br />
Die komplette Analyse ist bei <a href="http://www.webpagetest.org/result/091018_2J34/" title="webpagetest.org">webpagetest.org</a> zu finden. 
            </div>
        </content>
        
    </entry>
    <entry>
        <link href="http://www.nicosteiner.de/archives/224-Expires-Header-besser-verstehen.html" rel="alternate" title="Expires Header besser verstehen" />
        <author>
            <name>Nico Steiner</name>
                    </author>
    
        <published>2010-02-07T15:14:46Z</published>
        <updated>2010-09-30T18:57:20Z</updated>
        <wfw:comment>http://www.nicosteiner.de/wfwcomment.php?cid=224</wfw:comment>
    
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://www.nicosteiner.de/rss.php?version=atom1.0&amp;type=comments&amp;cid=224</wfw:commentRss>
    
            <category scheme="http://www.nicosteiner.de/categories/3-Referenzen" label="Referenzen" term="Referenzen" />
    
        <id>http://www.nicosteiner.de/archives/224-guid.html</id>
        <title type="html">Expires Header besser verstehen</title>
        <content type="xhtml" xml:base="http://www.nicosteiner.de/">
            <div xmlns="http://www.w3.org/1999/xhtml">
                Anhand eines unserer aktuellen Projekte möchte ich zeigen, wie die genannte Technologie in Hinblick auf die Performance einer Website zu verstehen ist.<br />
<br />
Folgende Statistik habe ich mit der Firefox Extension <a href="http://developer.yahoo.com/yslow/" title="Yahoo! Developer Network">YSlow</a> erstellt. Oben ist die Verteilung der Ressourcen bei einem ersten Request mit leerem Cache zu sehen. Der Bereich darunter zeigt die Verteilung bei einem zweiten Request unter Ausnutzung des Caches.<br />
<br />
<!-- s9ymdb:142 --><img class="serendipity_image_center" width="465" height="473" src="http://www.nicosteiner.de/uploads/weight-graphs.png" alt="YSlow Weight Graphs" /><br />
<br />
Der obere Bereich zeigt die typischen Ressourcen einer Seite. Etwas ungewöhlich sind die 2 XML-HTTP-Requests. Dahinter verbergen sich JavaScripte, welche asynchron mit der <a href="http://stevesouders.com/efws/managed-xhr.php" title="Even faster Websites">Managed XHR Technik</a> von Steve Souders in die Seite integriert werden.<br />
<br />
Interessanter in Bezug auf die erwähnte Technologie ist der untere Bereich, nutzt man Expires Header doch, um das Caching-Verhalten einer Seite positiv zu beeinflussen. Hier ist zu sehen, dass Scripte und Stylesheets nicht mehr aufgeführt werden. Dies ist wenig verwunderlich, da wir diese bereits mit <a href="http://stevesouders.com/hpws/rule-expires.php" title="Steve Souders">Far Future Expires Headern</a> versehen haben.<br />
<br />
<!-- s9ymdb:144 --><img class="serendipity_image_center" width="700" height="220" src="http://www.nicosteiner.de/uploads/expires-header1.png" alt="Expires Header für CSS und JavaScript" /><br />
<br />
Das Neuladen des HTML-Dokuments ist gewollt und wird mit einem in der Vergangenheit liegenden Expires Header erzwungen. Wir erzwingen für diesen Fall das Neuladen, da das Dokument dynamisch generiert wird und sich von einem Aufruf zum nächsten verändern kann.<br />
<br />
Neben dem HTML-Dokument erzeugen sämtliche Grafiken der Seite erneut Requests. Bei diesen steht die Auslieferung eines Expires Header momentan noch aus. Was im ersten Moment nur nach einer Einstellung in den Apache-Konfigurationen klingt, wird auf den zweiten Blick sehr viel komplexer, möchte man durch eine möglichst transparente Versionierung der Grafiken ein Neuladen bei Veränderungen erzwingen. Zumindest ist durch korrekte ETags sichergestellt, dass lediglich Requests in Form eines <a href="http://ruturajv.wordpress.com/2005/12/27/conditional-get-request/" title="Conditional GET Requests">Conditional GET</a> gemacht werden - die Daten selbst werden also nicht erneut übertragen. Allerdings braucht solch ein Request für den gesamten Roundtrip auch etwas Zeit - bei 40 Requests macht das in einem modernen Browser wie dem Firefox immer noch ganze 2 Sekunden aus!<br />
<br />
<strong>Nachtrag:</strong> Die Grafiken werden mittlerweile mit Hilfe des <a href="http://www.nicosteiner.de/archives/275-Content-Delivery-Server-online!.html">Content Delivery Server</a> mit Expires Header ausgeliefert. 
            </div>
        </content>
        
    </entry>
    <entry>
        <link href="http://www.nicosteiner.de/archives/274-Speaker-auf-dem-PHP-World-Kongress-2010.html" rel="alternate" title="Speaker auf dem PHP World Kongress 2010" />
        <author>
            <name>Nico Steiner</name>
                    </author>
    
        <published>2010-09-29T15:38:54Z</published>
        <updated>2010-09-29T15:45:04Z</updated>
        <wfw:comment>http://www.nicosteiner.de/wfwcomment.php?cid=274</wfw:comment>
    
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://www.nicosteiner.de/rss.php?version=atom1.0&amp;type=comments&amp;cid=274</wfw:commentRss>
    
            <category scheme="http://www.nicosteiner.de/categories/3-Referenzen" label="Referenzen" term="Referenzen" />
    
        <id>http://www.nicosteiner.de/archives/274-guid.html</id>
        <title type="html">Speaker auf dem PHP World Kongress 2010</title>
        <content type="xhtml" xml:base="http://www.nicosteiner.de/">
            <div xmlns="http://www.w3.org/1999/xhtml">
                <!-- s9ymdb:180 --><img class="serendipity_image_left" width="200" height="120" style="float: right; border: 0px; padding-left: 15px;" src="http://www.nicosteiner.de/uploads/php-worl-kongress-speaker-2010.gif" alt="" />Ich werde am 9. November auf dem <a href="http://www.phpworld-kongress.de/">PHP World Kongress</a> einen Vortrag zur Verbesserung der Website Performance halten.<br />
<br />
<strong>Abstract</strong><br />
Wie verbessere ich die Ladezeiten meiner Websites und welche Vorteile ergeben sich daraus? Auf der Basis allgemeingültiger Regeln werden in diesem Vortrag Lösungen vorgestellt, wie sie im Umfeld der 1&1 Shopsysteme entstanden sind. Es wird weiterhin erläutert, wie zentralisierte Technologien dafür sorgen können, dass diese Optimierungen projektübergreifend angewendet werden, Kennzahlen erhoben und mögliche Schwachstellen identifiziert werden können. 
            </div>
        </content>
        
    </entry>
    <entry>
        <link href="http://www.nicosteiner.de/archives/273-Promote-JS!-Better-Docs-For-Us,-By-Us!.html" rel="alternate" title="Promote JS! Better Docs For Us, By Us!" />
        <author>
            <name>Nico Steiner</name>
                    </author>
    
        <published>2010-09-26T20:32:26Z</published>
        <updated>2010-09-26T20:32:26Z</updated>
        <wfw:comment>http://www.nicosteiner.de/wfwcomment.php?cid=273</wfw:comment>
    
        <slash:comments>0</slash:comments>
        <wfw:commentRss>http://www.nicosteiner.de/rss.php?version=atom1.0&amp;type=comments&amp;cid=273</wfw:commentRss>
    
    
        <id>http://www.nicosteiner.de/archives/273-guid.html</id>
        <title type="html">Promote JS! Better Docs For Us, By Us!</title>
        <content type="xhtml" xml:base="http://www.nicosteiner.de/">
            <div xmlns="http://www.w3.org/1999/xhtml">
                <a href='https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/String' title='JavaScript JS Documentation: JS String toLocaleLowerCase, JavaScript String toLocaleLowerCase, JS String .toLocaleLowerCase, JavaScript String .toLocaleLowerCase'><img src='http://static.jsconf.us/promotejsvs.png' height='280' width='160' alt='JavaScript JS Documentation: JS String toLocaleLowerCase, JavaScript String toLocaleLowerCase, JS String .toLocaleLowerCase, JavaScript String .toLocaleLowerCase'/></a> 
            </div>
        </content>
        
    </entry>

</feed>
