Jeder darf mal: .htaccess-Bullshit

Geschwindigkeit ist ja der neue Backlink und jeder meint, da seinen Senf dazugeben zu müssen. Und egal wie blödsinnig die Umsetzung ist, es wird sich immer wer finden, der’s geil findet.

Zwei Sachen dazu:
Das hat im .htaccess nichts verloren. Über Performance schreiben und dann das .htaccess-File zumüllen ist wie bei 280 auf der linken Spur über den hohen Benzinpreis jammern. Wer Zugriff auf seine Apache-Konfiguration hat sollte das dort unterbringen. Immer.
Hartkodierte Datumsangaben, die, vom heutigen Standpunkt aus, weit in der Zukunft liegen, sind eine ganz schlechte Idee. Ist ja nicht so, dass wir das nicht erst hatten. mod_expires bringt da ein viel einfacheres Mittel, um genau das Problem zu vermeiden.

Finger raus aus der Keksdose!

Eine sehr einfache Methode, Bandbreite zu sparen und Daten schneller auszuliefern ist, sie ohne Cookies zu senden.

Google sagt:

Serve static content from a cookieless domain

Liegen dynamische Daten und Bilder, Stylesheets und Javascript-Dateien auf der gleichen Domain sendet der Browser bei jeder Anfrage die Cookies, die er für diese Domain gespeichert hat, mit. Was absolut unnötig ist, denn die wichtigste Eigenschaft von statischem Content ist, dass er genau das ist: Statisch.

Also raus mit den Cookies. Einfachste Lösung: Eine Subdomain anlegen, z.B. static.domain.de, als ServerAlias in der Apache-Konfiguration hinzufügen und alle Bilder, Javascripts und Stylesheets über diese URL adressieren. Alternativ kann man es machen wie Google und das über eine eigene Domain steuern. Oder gleich über ein CDN. Dazu aber später mal mehr.

ga.js aktuell halten

Es gibt ja für jede Lösung ein Problem, so natürlich auch für mögliche Änderungen an ga.js, wenn man die Datei, um sie gzip-komprimiert auszuliefern, selber hosten will.

Ein bisschen Shell-Scripting sorgt dafür, dass die Datei von Google geladen und an die richtige Stelle kopiert wird:

#!/bin/sh
# TMP DIRECTORY
MYTMP=/tmp
# SAVE ga.js HERE
INSTALL_IN=/htdocs/domain.de/javascript/
# RESOURCE URL
GOOGLE_GA_URL=http://www.google-analytics.com/ga.js
# USER-AGENT
UA="Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.3) Gecko/20070309 Firefox/2.0.0.3"
# CD TO TMP DIRECTORY
cd $MYTMP
# DOWNLOAD THE FILE
curl --header "Pragma:" -f -s -A "${UA}" -m 1800 --retry 15 --retry-delay 15 --max-redirs 8 -O $GOOGLE_GA_URL
# GIVE FILE CORRECT PERMISSIONS
chmod 644 $MYTMP/ga.js
# COPY FILE TO SITE DIRECTORY
cp -r $MYTMP/ga.js $INSTALL_IN
# RETURN TO OLDPWD
cd $OLDPWD
exit 0;

Als Cronjob ausgeführt wird damit ab sofort regelmäßig die aktuelle Version der ga.js von Google geholt.

Hält man sich darüber hinaus an die Empfehlung von Google und versieht seine statischen Dateien mit weit in der Zukunft liegenden Expire-Headern sollte man bei der Gelegenheit dann auch gleich sicherstellen, dass die Datei einen deutlich niedrigeren Expire-Header bekommt, sonst kann man sich die ganze Aktion auch gleich sparen:

<Files ga.js>
ExpiresByType application/javascript "access plus 1 week"
</Files>

Google vs. Google: ga.js gzip-komprimieren

Geschwindigkeit ist der neue heiße Scheiß. Google trommelt ganz vorne mit, klar, für die ist (Rechen-)zeit bares Geld. Das Firebug-Plugin Pagespeed gibt es schon länger, unter Let’s make the web faster hat der Suchmaschinenriese zahlreiche Informationen an zentraler Stelle gesammelt und seit kurzem hat auch eine Site Performance Auswertung Einzug in die Webmastertools gehalten.

Darin finden sich dann auch so interessante Sachen:
Google Site Performance bemängelt Google Analytics

Wirklich eine klasse Idee. Sollte Google vielleicht jemandem bei Google mal sagen.

Natürlich kann man die Datei auch selbst hosten.

Vorteile:

  • Man spart sich einen DNS-Lookup für www.google-analytics.com
  • Man kann die Datei komprimiert ausliefern
  • Eine Nichterreichbarkeit von www.google-analytics.com blockiert nicht den Ladevorgang

Auf der anderen Seite steht dem natürlich entgegen:

  • Der User hat, aufgrund der hohen Verbreitung von Google Analytics, die Datei möglicherweise schon im Cache
  • Ändert Google etwas an ga.js liefert man nach wie vor eine veraltete Datei aus.

Am Ende muss also jeder selbst entscheiden, ob sich für ihn das Einsparpotential durch die Komprimierung rechnet.

Umziehen Part 3: Mit mod_proxy von Server zu Server

In Teil 1 und 2 haben wir uns damit beschäftigt, wie man Browser und Suchmaschinen den Weg zu einer neuen Ressource weißt, wenn sich deren URL geändert hat. In diesem Teil geht es um den einfachen Umzug auf einen neuen Server.

Im Folgenden geht es ausschließlich um den Umzug eines Webauftritts von einem Server auf einen anderen. Prinzipiell ist das ganze auch bei Shared Hosting möglich, gewisse Dinge wie der Zugriff auf die hosts-Datei sind dabei aber unter Umständen nicht möglich. mod_proxy sollte installiert und aktiviert sein. Der Zugriff auf die DNS-Konfiguration ist Bedingung.

Mit steigenden Zugriffszahlen wachsen auch die Anforderungen an die Hardware. Gerade wenn in Spitzenzeiten die Antwortzeiten in den Keller gehen ist es Zeit, sich Gedanken über einen Serverumzug zu machen. Oder dieser Schritt steht turnusmäßig sowieso an, weil die aktuelle Hardware veraltet ist. Doch wie die Besucher problemlos auf die neue Maschine migrieren, wie verhindern, dass Zugriffe auf die alte und die neue Maschine zeitgleich stattfinden? Schließlich ist das DNS-System zwar robust, aber mitunter nicht sonderlich schnell.

Wir möchten also unseren aktuellen Webauftritt unter www.domain.de, der auf dem Server mit der IP 8.8.4.4 liegt, auf einen neuen Server mit der IP 8.8.8.8 umziehen.

Der erste Schritt ist das ‘Anlegen’ einer Subdomain im lokalen hosts-File am Arbeitsrechner. Diese findet sich auf unixoiden Betriebssystemen in /etc/hosts, unter Windows in C:WINDOWSsystem32driversetchosts und kann mit jedem beliebigen Texteditor bearbeitet werden. Dort fügen wir einen neuen Eintrag hinzu:

8.8.8.8     new.domain.de

Dieses Vorgehen hat gegenüber einem richtigen DNS-Eintrag den Vorteil, dass new.domain.de nur vom Arbeitsrechner aus erreichbar ist und man so auf gesonderte Sicherungsmaßnahmen am neuen Server verzichten kann, wie sie sonst nötig wären, um eine vorzeitige Indizierung der Inhalte durch Google zu verhindern. Hat man keinen Zugriff auf die hosts-Datei am alten Server muss dieser Eintrag unbedingt über das DNS-System erfolgen und sollte mit entsprechendem Vorlauf (mind. 48 Stunden) gemacht werden!

Auf dem neuen Server richtet man nun new.domain.de ein und transferiert den aktuellen Webauftritt vollständig auf die neue Maschine, kopiert also sowohl Dateien als auch Datenbankinhalte auf den neuen Server und passt, sofern erforderlich, die Konfigurationsdateien an. Anschließend testet man alles auf Herz und Nieren.

Das Logfile zu Hilfe nehmend, um den idealen Transferzeitpunkt zu ermitteln, geht es dann an den eigentlichen Umzug. Zunächst muss verhindert werden, dass der alte Auftritt weiterhin genutzt werden kann. Die .htaccess auf dem alten Server wird daher durch die folgende ersetzt:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !.*storedown.*$
RewriteRule .* /storedown.php [L]

storedown.php sollte nicht nur kurz darüber informieren, dass hier gerade ein Umzug im Gange ist, sondern auch einen 503-Header senden, damit auch Google Bescheid weiß:

<?php
header("HTTP/1.1 503 Service Temporarily Unavailable");
header("Status: 503 Service Temporarily Unavailable");
header("Retry-After: 360");
header("Connection: Close");
?>
<!DOCTYPE HTML>
<html lang="en-US">
<head>
	<title>503 Service Temporarily Unavailable</title>
	<meta charset="UTF-8">
</head>
<body>
	<h1>Service Temporarily Unavailable</h1>
	<p>The server is temporarily unable due to maintenance downtime. Please try again later.</p>
</body>
</html>

Der Retry-After-Header sollte einen realistischen Wert in Sekunden enthalten, bis wann der Umzug abgeschlossen sein wird.

Ein letzter Sync zwischen altem und neuen Server stellt sicher, dass auf der neuen Maschine auch der letzte Stand verfügbar sein wird. Der neue Server wird jetzt auf die eigentliche Domain www.domain.de konfiguriert und /etc/hosts auf dem alten Server um folgenden Eintrag ergänzt:

8.8.8.8     www.domain.de

.
Jetzt nur noch die .htaccess auf dem alten Server ersetzen:

RewriteEngine On
RewriteRule ^(.*) http://www.domain.de/$1 [P]

Ohne Zugriff auf die hosts-Datei am alten Server muss mod_proxy angewiesen werden, auf die zuvor eingerichtete Subdomain new.domain.de zuzugreifen:

RewriteEngine On
RewriteRule ^(.*) http://new.domain.de/$1 [P]

Jetzt kann die DNS-Änderung für www.domain.de beantragt werden. Alle Anfragen, die bis dahin noch auf dem alten Server 8.8.4.4 eintreffen, werden mittels mod_proxy und Dank dem Eintrag in der hosts-Datei an den neuen Server weitergereicht – für den Besucher vollkommen transparent.

Umziehen Part 2: 301 mit RedirectPermanent

Weil das gerade so schön durch Abakus durchwabert und ich ja im ersten Teil dieser kleinen Serie strikt davon abgeraten habe, 301-Umleitungen mit RedirectPermanent zu machen, hier noch ein paar ergänzende Worte dazu:

In Teil 1 ging es mir darum, dass schlicht und ergreifend die Domain gewechselt werden, die Inhalte des Auftritts aber brav an der alten Stelle bleiben sollen. RedirectPermanent hilft hier nicht weiter. Der Eintrag in der .htaccess

1
	RedirectPermanent / http://seorockstar.de/

würde wieder auf diesen Auftritt verweisen. Wir würden uns also eine Endlosschleife bauen. Wir brauchen also eine Überprüfung, ob die URL, unter der der Auftritt erreicht wird, überhaupt unterschiedlich zu der ist, zu der wir umleiten wollen. Und das geht schlicht und ergreifend nur mit mod_rewrite und der RewriteCond.

Für was ist dann aber RedirectPermanent überhaupt nützlich?

Beispielsweise dann, wenn man auf eine Domain verweist, die sich mit dieser nicht das physikalische Verzeichnis teilt, man also nicht erst prüfen muss, welche Domain der Besucher aufgerufen hat, bietet sich RedirectPermanent an. Im Vergleich zu mod_rewrite hat eine mod_alias-Lösung nämlich vor allem Performancevorteile, weil nicht erst die RewriteEngine gestartet und Ressourcen zehrend ein regulärer Ausdruck darauf hin überprüft werden muss, ob er zutrifft oder nicht. Auch ist mod_alias in der Lage, den Pfad-Teil der Domain korrekt anzuhängen, der Besucher wird also nicht einfach auf die Startseite geworfen, wenn die Umleitung greift.

Umziehen Part 1: 301

Die Gründe dafür sind vielfältig: Die neue Firmen-CI ist allergisch auf Bindestriche, auch in Domainnamen, man hat sich an der Domain für sein privates Blog sattgesehen oder will mal den großen Subdomain-Aufstand proben. Also registriert man eine neue Domain und zieht den bestehenden Webauftritt dahin um.

Soweit die Theorie. Aber das soll natürlich nicht dazu führen, dass plötzlich alle Links von anderen Seiten oder auch aus den SERPs ins Leere laufen, gleichzeitig soll aber der Auftritt auch nicht unter beiden Domains erreichbar sein – und sei es nur die Startseite, weil moderne CMS- und Blogginglösungen das spätestens ab der zweiten Ebene wieder gerade biegen.

Die Lösung lautet: 301. Wikipedia weiß dazu:

Die angeforderte Ressource steht ab sofort unter der im „Location“-Header-Feld angegebenen Adresse bereit. Die alte Adresse ist nicht länger gültig.

Also genau das, was wir wollen. Immer wieder stolpert man darüber, dass man das mit der Apache-Direktive RedirectPermanent machen soll, aber dazu kann man nur sagen: Finger weg! RedirectPermanent ist Teil von mod_alias und unterstützt daher keine regulären Ausdrücke und keine Bedingungen, wann eine Regel greift und wann nicht. Aber nur damit macht das ganze eigentlich richtig Spaß, wobei bei der Umleitung einer kompletten Domain auf eine andere das ganze auch mit regulären Ausdrücken nicht wirklich kompliziert ist:

1
2
3
4
5
6
<IfModule mod_rewrite.c>
RewriteEngine On
 
RewriteCond %{HTTP_HOST} !^www.notaseo.de$
RewriteRule ^(.*)$ http://www.notaseo.de/$1 [L,R=301]
</IfModule>

Die erste Zeile prüft zunächst, ob mod_rewrite überhaupt verfügbar ist. Was mittlerweile bei so ziemlich jedem Provider der Fall sein dürfte. Die zweite schaltet die Umschreibemaschinerie an. Zeile drei ist eine Bedingung, die prüft, ob der Host, mit dem die Website aufgerufen wurde, nicht www.notaseo.de ist – nur dann greift die nachfolgende Regel, die einfach alles, was nach dem Host kommt, nimmt, in eine Variable $1 schreibt und auf die Zieldomain umleitet. Die Angaben in Klammern sagen aus, dass danach, sollte die Datei weitere Regeln beinhalten, diese nicht mehr abgearbeitet werden (L wie Last) und die Umleitung (R wie Redirect) per 301 erfolgen soll.

Das ganze hat noch einen angenehmen Nebeneffekt: Aufrufe ohne www oder mit irgendwelchen anderen Subdomains leiten immer sauber auf die eigentliche Domain um und man stellt so sicher, dass eine Ressource unter einer kanonischen URL erreichbar ist.

Tut man das ganze aufgrund eines Domainwechsels und nicht, um die Kanonizität sicherzustellen sollte man natürlich anschließend noch versuchen, Backlinks auf die alte Domain durch die Webmaster ändern zu lassen. Schließlich will man die alte Domain auch irgendwann mal kündigen.

Prüfen, ob alles so funktioniert wie gedacht und auch der richtige Statuscode zurückgegeben wird kann man solche Sachen mit diversen Online- und Offlinetools, etwa dem Web-Sniffer oder dem HTTP Client.

Page 9 of 9« First...56789