Das Putzlowitsch Test- und SEO-Blog
Stichwort: Permalink

WordPress mit Permalinks – den Webserver entlasten

Wie WordPress Permalinks verarbeitet

Durch Permalinks bekommen Artikel und Seiten lesbare URLs und auch Struktur. Alle Artikel in der Kategorie ‚Wordpess‘ können mit schnurpsel.de/themen/wordpress/ aufgerufen werden, das Monatsarchiv für Juli 2010 mit schnurpsel.de/date/2010/07/.

Auf dem Webserver existiert aber kein Verzeichnis /themen/wordpress/ oder /date/2010/07/. Damit die Seiten trotzdem aufgerufen werden können, erstellt WordPress eine einfache Regel für das Rewrite-Modul des Apache-Webservers:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]

Diese drei Zeilen führen dazu, das alles, was nicht tatsächlich als Datei oder Verzeichnis auf dem Server existiert, einfach an die index.php von WordPress durchgereicht wird. WordPress kümmert sich nun darum, ob es z.B. eine Kategorie „WordPress“ gibt, stellt die Liste mit den passenden Artikeln zusammen und gibt sie aus.

Was es alles nicht gibt

Im Moment sind wohl mal wieder ein paar Bots oder Skriptkiddies unterwegs, die einfach versuchen, irgendwelche php-Skripte aufzurufen, um mögliche Sicherheitslücken ausnutzen zu können. Das sieht dann etwa so aus:

/scripts/setup.php
/pma/scripts/setup.php
/phpMyAdmin/scripts/setup.php
/phpmyadmin/scripts/setup.php
/myadmin/scripts/setup.php

Solche Dateien gibt es hier allerdings nicht. Auch andere Sachen können zu fehlerhaften Aufrufen führen, z.B. Standard-Icons wie favicon.ico oder apple-touch-icon.png, die manche Browser einfach aufrufen oder durch Nutzer aus der Bildersuche falsch kopierte BILd-URLs.

Durch die für die Permalinks notwendigen mod_rewrite-Regeln werden alle dies Aufrufe nun an WordPress weitergeleitet. WordPress wird geladen, stellt eine Datenbankverbingung her, klappert die internene Rewriteregeln ab um schließlich nur festzustellen, daß es mit dem Aufruf nichts anfangen kann. Dann gibt WordPress schließlich auch nur eine Fehlerseite aus, die möglicherweise auch noch aufwändig gestaltet ist und unnötig viel Daten als Antwort zurücküberträgt.

WordPress und den Webserver entlasten

Damit nun nicht WordPress wegen jeder Kleinigkeit behelligt werden, kann man eine spezielle Regel der WordPress-Regel vorschalten, die einfach gegebenfalls die Abarbeitung der Rewrite-Regeln beendet:

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule \.[^\.]+$ - [L]
</IfModule>

Die Idee dabei ist, daß alle Permalink-URLs normalerweise keine Dateierweiterung wie .html, .jpg oder .php haben. Falls nun eine Datei nicht existiert (RewriteCond) und diese Datei mit einem Punkt und mindestens einem weiteren Zeichen endet, wird die Abarbeitung der Regeln an dieser Stelle beendet (RewriteRule). Diese Zeilen müssen vor den WordPress-Regeln stehen.

WordPress bekommt diese Aufrufe nicht mehr zu sehen, der Fehler wird einfach vom Webserver behandelt. Hier kommt dann auch eine konfigurierte und vorhanden benutzerdefinierte Fehlerseite zu Anwendung.

Ich weiß, es gibt auch Blogger, die aus welchen Gründen auch immer, die Permalinks mit einem abschließenden .html konfiguriert haben. Aber auch das ist kein Problem, es muß nur eine Zeile hinzugefügt werden, welche die Regel für die Endung .html (oder eine andere) ungültig macht:

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI}	!\.html$
RewriteRule \.[^\.]+$ - [L]
</IfModule>

Optimierte Version

Mann kann die zusätzlichen Bedingungen auch direkt in die WordPress-Rules einfügen. Nachteil hierbei ist aber, daß sie bei Änderungen an den Permalinkeinstellungen verloren gehen, weil WordPress den Block zwischen # BEGIN WordPress und # END WordPress neu schreibt:

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI}	!\.[^\.]+$
RewriteRule . /index.php [L]
</IfModule>
# END WordPress

Die Version mit Endung .html:

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI}	!\.[^\.]+$ [OR]
RewriteCond %{REQUEST_URI}	\.html$
RewriteRule . /index.php [L]
</IfModule>
# END WordPress

Plugin-Version

Angeregt durch die Kommentare von Ralf habe ich nun eine Plugin-Version fertig gestellt.

Download: 123 Rewrite Error 0.10

Das Plugin schreibt die Regeln beim Aktivieren, Deaktivieren und bei Änderungen an der Permalinkstruktur wie bei der Optimierten Version beschrieben automtisch mit den WordPress-RewriteRules in die .htaccess. Dabei wird auch gleich berücksichtigt, ob in der Permalinkstruktur eine Erweiterung wie .html angegeben wurde.

Fazit

Wieviel Serverlast oder Traffic durch diese Maßnahme eingespart wird, kann ich nicht sagen. Das hängt sicher auch vom Nutzungsprofil und der Konfiguration der Website ab. Aber warum sollte man solch eine einfache Möglichkeiten auslassen, um WordPress und dem Webserver das Leben ein bißchen leichter zu machen.

8 Kommentare »

Permalinks – Was verwenden die 33 deutschen Top-Blogs

Welcher Permalink ist das beste Ding?

Die Diskussion taucht immer wieder mal auf, wie sieht optimalerweise ein Permalink, also die Struktur der URL aus. Sollten das Datum oder die Artikel-ID enthalten sein, ist es sinnvoll Kategorien oder Tags mit aufzunehmen?

Eine allgemeingültige und endgültige Empfehlung kann es nicht geben, wenn man die unterschiedlichen Sichtweisen dazu berücksichtigt, die dann zu eher widersprüchliche Aussagen führen.

Betreibt man ein Blog im Sinne eines Tagebuches, ist sicher das Datum oder Bestandteile davon eine gute Wahl. Aus SEO-Gesichtspunkten bzw. für eine eher thematische Ausrichtung wird oft die Kategorie mit in die Permalinkstruktur aufgenommen. Für eine Webseite mit vielen Schreibern könnte auch der Autorenname eine geeignete Option sein.

Ich habe mir einfach mal die Permalink-Struktur der 33 deutschen Top-Blogs angesehen. Vielleicht läßt sich ja daraus eine Empfehlung ableiten.

Die Permalink-Struktur der 33 deutschen Top-Blogs

Zunächst stellt sich natürlich die Frage, welche sind denn die Top-Blogs in Deutschland? Auch hier kann man sich endlos streiten, wenn man will. Ich habe als erste Näherung einfach die aktuell zusammengerechnete Liste von heute, dem 24.02.2010, genommen. Die Permalinkstruktur habe ich in Gruppen zusammengefaßt, vor dem jeweiligen Blog steht der aktuelle Platz in der Top-33-Liste :

Mehr als die Hälfte (57,6%) der Top-33-Blogs verwendet neben dem Artikelnamen das Datum oder einen Bestandteil davon in der URL. Bei allein fast 40% findet man das komplette Datum mit Jahr, Monat und Tag im Permalink. Gut 18% benutzen nur den Namen des Artikels als Permalink und weitere etwa 12% kombinieren dazu noch eine Nummer (Artikel-ID). Immerhin knapp 10% der Top-Blogs verwenden keine Permalinks, sondern setzen auf die Artikelnummer als URL-Parameter (?id=1234).

Erste Ableitung des Permalink-Aufbaus

Wenn man Permalinks verwendet, ist der Artikelname (in seiner Umwandlung zu einem URL-Pfad) gewissermaßen eine feste Größe. Die Einbeziehung des Datums oder von Teilen kann so schlecht nicht sein, diese Verwendet ein Großteil der Top-Blogs. Auch ganz auf Permalinks zu verzichten, hat gewisse Vorteile. Die URLs sind kurz und bleiben immer gültig, auch wenn man mal was am Artikel-Titel, dem Datum oder sonstigen Einflußfaktoren ändert.

Ich habe mir stichprobenartig noch weitere Blogs der Top-100 angesehen und zumindest keine Seite entdeckt, die etwa die Kategorie oder gar Tags in der URL verwendet. Mal davon abgesehen, daß Tags bei WordPress bis zur Version 2.9.x nicht als Bestandteil der Permalinks funktionieren (obwohl in der Dokumentation genannt), gibt es auch noch andere Probleme.

Kategorie oder Tag im Permalink

In WordPress kann man Artikel in mehreren Kategorien ablegen. Einem Artikel können zudem auch mehrere Tags zugeordnet werden. Verwendet man Kategorien oder Tags in Permalinks, erstellt WordPress die die URL aus der Kategorie oder dem Tag mit der kleinsten ID. Ändert man nun die Kategoriezuordnung oder die Tags, kann sich möglicherweise auch die URL ändern.

Das ist aber erstmal nicht weiter schlimm, denn der Artikel wird auch weiterhin mit der alten Kategorie gefunden und angezeigt. WordPress geht sogar soweit, einfach die Kategorie beim Auflösen der Permalinks zu ignorieren. Damit ergeben sich dann theoretisch beliebig viele URLs für einen Artikel.

Als Beispiel ist das auf meinem Testblog zu sehen. Die Permalink-Struktur sieht so aus:

/%category%/%postname%/

Der Artikel ist in der Kategorie „Allgemein“ einsortiert, die URL sieht so aus:
http://testblog.schnurpsel.de/allgemein/hallo-welt/

Er ist aber auch mit der Kategorie „Blafasel“, „Hundekuchen“ oder „Gibtesnicht“ aufrufbar:
http://testblog.schnurpsel.de/blafasel/hallo-welt/
http://testblog.schnurpsel.de/hundekuchen/hallo-welt/
http://testblog.schnurpsel.de/gibtesnicht/hallo-welt/
Genau, diese Kategorien gibt es gar nicht.

Man hat damit potentiell also ganz viel bösen „Duplicate content“ (DC). Da sage noch einer, die Kategorie im Permalink sei unter SEO-Gesichtspunkten empfehlenswert. ;-)

Permalink, so oder so

Letztendlich muß jeder selbst entscheiden, ob und wie er seine Permalinks gestaltet. Bei Putzlowitsch habe ich mich für das Datum entschieden, da ich dort eher im Sinne eines Tagebuchs schreibe. Hier verwende ich eine Kombination aus Artikelname und Artikel-ID, weil die sichtbare ID schnelle interne Links mit dem 123 IntLink-Plugin ermöglicht. Bei Twitter verwende ich übrigens gerne die WP-Shortlinks mit der ID als URL-Parameter, die sind schön kurz und funktionieren auch ohne Shortlink-Dienst.

1 Kommentar »

Über kurz oder lang, Twitter läßt wieder lange Links lang

TwitterDas habe ich grad erst zufällig entdeckt. Twitter hat beim Webinterface die Zwangsverkürzung von Links ab 30 Zeichen Länge abgeschaltet. Somit kann ich z.B. für meine Blogartikel wieder die Permalinks in voller Schönheit posten, ohne die WordPress-Shortlinks nutzen zu müssen.

Einen kleinen Hinweis daraus findet man auch im Twitter-Hilfe-Forum:

„Twitter used to shorten links automatically but we do not any longer.“

So, mal sehen, ob es stimmt :-)

Nachtrag 22:00 Uhr:
Ja, funktioniert so weit. Nur habe ich nicht bedacht, das bei einem Retweet dann eventuell die 140-Zeichengrenze überschritten wird. Das ist zwar direkt auf twitter.com nicht weiter schlimm und wird trotzdem in voller Länge angezeigt:
Twitter Retweet größer als 140 Zeichen

Im Feed und vermutlich beim Zugrifff mit den API-Funktionen wird allerdings ab 137 Zeichen abgeschnitten. Da nun der Link am Ende stand, stimmt der dann nicht mehr. So haben dann diverse Twitter-Abfrage-Bots bversucht, diesen falschen Link aufzurufen:

/ueber-kurz-oder-lang-twitter-laesst-wieder-lan

Naja, ist halt Pech. Da werde ich demnächst versuchen, die Links möglichst nicht am Ende zu platzieren. Oder ich nehme doch wieder die wordpresseigenen Kurzlinks mit der Artikel-ID.

0 Kommentare »

WordPress für statische Seiten optimieren

WordPress und Permalinks

In WordPress kann man für schönere URLs die Permalinks aktivieren. Diese werden nur für die Struktur der Artikel-URL festgelegt, zusätzlich kann ein Präfix für Kategorien und Tags vorgegeben werden, für Seiten jedoch gibt es keine extra Einstellmöglichkeit.

Für Artikle steht eine Vielzahl von von Platzhaltern (Variablen) zur Verfügung, die bei Zusammensetzen der URL durch die jeweiligen Daten des konkreten Artikels ersetzt werden.

Auch wenn man Permalinks nur für die Artikle wirklich konfigurieren kann, wirken sich die dort gewählten Optionen auch auf die Seiten und andere URLs in WordPress aus. Einen sichtbaren Effekt hat die Entscheidung, ob man die Permalinks mit einem Schrägstrich abschließt oder nicht. Entsprechend erhalten auch alle anderen von WordPress generierten URLs diesen Schrägstrich oder nicht. Das gilt übrigens nur für den Schrägstrich (Slash), alle anderen Endungen wie z.B. .html werden dabei nicht übernommen.

WordPress und Rewrite-Rules

Damit WordPress die Permalinks wieder in konkrete Artikel- und Seiten-IDs auflösen kann, wird eine Liste von Regeln (RewriteRules) erstellt, die sequentiell abgearbeitet wird. Mit dem ersten passenden Treffer wird dann die Datenbankabfrage für einen Artikel oder eine Seite, für eine Kategorie- oder Tagübersicht oder einen Feed usw. erstellt.

Wie diese interne Liste aussieht hängt unter anderem auch davon ab, welche Struktur für die Artikel bei der Permalinkkonfiguration gewählt wird. WordPress muß Artikel von Seiten eindeutig unterscheiden können und das funktioniert nur, wenn die Permalinks als ersten Platzhalter keinen variablen Wert wie Postname (%postnam%), Kategorie (%category%), Tag (%tag%) oder Autor (%author%) enthalten. Andernfalls werden für jede statische Seite jeweils 11 Einträge in der Liste der RewriteRules erstellt, die so aussehen:

[seite-1/attachment/([^/]+)/?$] => index.php?attachment=$matches[1]
[seite-1/attachment/([^/]+)/trackback/?$] => index.php?attachment=$matches[1]&tb=1
[seite-1/attachment/([^/]+)/feed/(feed|rdf|rss|rss2|atom)/?$] => index.php?attachment=$matches[1]&feed=$matches[2]
[seite-1/attachment/([^/]+)/(feed|rdf|rss|rss2|atom)/?$] => index.php?attachment=$matches[1]&feed=$matches[2]
[seite-1/attachment/([^/]+)/comment-page-([0-9]{1,})/?$] => index.php?attachment=$matches[1]&cpage=$matches[2]
[(seite-1)/trackback/?$] => index.php?pagename=$matches[1]&tb=1
[(seite-1)/feed/(feed|rdf|rss|rss2|atom)/?$] => index.php?pagename=$matches[1]&feed=$matches[2]
[(seite-1)/(feed|rdf|rss|rss2|atom)/?$] => index.php?pagename=$matches[1]&feed=$matches[2]
[(seite-1)/page/?([0-9]{1,})/?$] => index.php?pagename=$matches[1]&paged=$matches[2]
[(seite-1)/comment-page-([0-9]{1,})/?$] => index.php?pagename=$matches[1]&cpage=$matches[2]
[(seite-1)(/[0-9]+)?/?$] => index.php?pagename=$matches[1]&page=$matches[2]

Das mag bei wenigen Seiten zwar kaum ins Gewicht fallen, bei hunderten oder gar tausenden Seiten aber schon. Einerseits belegen diese vielen Regeln Speicher, andererseits müssen sie jedesmal abgearbeitet werden, bei z.B. 300 Seiten mehr als 3300 Listeneinträge. Probleme kann es auch beim Anlegen und Ändern von Seiten geben, denn die Liste muß dann jedesmal neu erstellt werden.

Permalinks für statische Seiten optimieren

Wenn man viele statische Seiten verwendet oder vielleicht gar keine Artikel (WordPress als CMS), sollte man als ersten Platzhalter (Strukturtag) in den Permalinks einen numerischen Wert wie Datum (year,monthnum,day), Zeit (hour,minute,second) oder die ID (post_id) verwenden. Die von WordPress zur Auswahl angebotenen Möglichkeiten erfüllen diese Bedingungen:

Tag und Name: /%year%/%monthnum%/%day%/%postname%/
Monat und Name: /%year%/%monthnum%/%postname%/
Numerisch: /archives/%post_id%

Für Benutzerdefinierte Einstellungen wären z.B. /%post_id%-%postname%/ geeignet. Es darf auch ein fester Text vor dem ersten numerischen Wert stehen, also z.B. /news/%post_id%-%postname%/.

Mit diesen Permalinkeinstellungen werden keine extra Rules je Seite erzeugt, das spart zumindest bei WordPressinstallationen mit sehr vielen statischen Seiten Speicherplatz und Abarbeitungszeit.

7 Kommentare »

Strato wird vernünfig, mod_rewrite funktioniert

Das ich das noch miterleben darf. Nachdem ja bereits vor einiger Zeit das memory_limit angehoben und der safemode ausgeschaltet wurde, ist nun eines der weiteren großen Ärgernisse beim Strato-Webhosting aus der Welt geschafft.

Seit kurzem unterstützt Strato das für Permalinks wichtige Modul mod_rewrite. Bisher mußte man sich da mit Tricks, wie einem vorangestellten index.php oder dem Fehler 404 Plugin behelfen. Jetzt funktioniert das einfach so, wie es von WordPress selbst vorgesehen ist, über ein paar mod_rewrite-Regeln.
Wenn Strato jetzt noch die Datenbank-Performance verbessert, könnte man aus WordPress-Sicht schon fast rundum zufrieden sein.

Nachtrag 09.04.2008: Seit heute findet man auch einen entsprechenden Artikel zu mod_rewrite in den Strato-FAQ.

27 Kommentare »

Es geht doch, Kontaktformular mit POST und Permalinks

Mein 123 No Rewrite Permalink Plugin hat einen kleinen Nachteil, es können keine Formulardaten per POST an eine Permalinkseite gesendet werden. Deshalb funktionieren z.B. Kontaktformular-Plugins wie der „DD Formmailer“ nicht. Ich habe auf der Pluginseite und auch bei meiner Strato-Permalink-Konfigurationsseite darauf hingewiesen.
Angeregt durch einen Beitrag im WP-Deutschland-Forum habe ich noch mal über das Problem nachgedacht und bin auf eine recht einfache Lösung gekommen. Diese ist zumindest dann praktikabel, wenn es nur um eine oder wenige Seiten mit Formularen geht, in der Regel wird es nur eine Seite für „Kontakt“ oder ähnliches sein. Am Beispiel des schon erwähnten DD-Formmailers werde ich die erforderlichen Schritte beschreiben. Ich gehe davon aus, daß das Formmailer-Plugin bereits installiert ist.

Zunächst wird eine neue statische Seite erstellt, die z.B. „Kontakt“ heißt. Hier wird der Text und Code für den Formmailer eingegeben. Die URL der Seite lautet dann beispielsweise

http://schnurpsel.de/kontakt/

Diese wird bei den Einstellungen für den DD-Formmailer als „Contact page“ eingetragen.

Dann wird eine Kopie der Datei index.php aus dem WordPress-Wurzelverzeichnis erstellt und bearbeitet.
Originale index.php:

<?php
/* Short and sweet */
define('WP_USE_THEMES', true);
require('./wp-blog-header.php');
?>

Bearbeitete index.php:

<?php
/* Short and sweet */
define('WP_USE_THEMES', true);
require('../wp-blog-header.php');
?>

Kleine Änderung, große Wirkung, es ist nur ein Punkt beim require hinzugekommen.
Nun wird per FTP im WP-Wurzelverzeichnis ein Unterverzeichnis /kontakt/ angelegt und die geänderte index.php dort hinein kopiert.

Das wars, jetzt kann man die Kontaktseite aufrufen und Daten absenden, sofern man sonst auch alles andere beim DD-Formmailer richtig konfiguriert hat.
Man kann das auch bei mir hier testen, unter Kontakt, wo sonst? :-)

Und zum Schluß noch ein wichtiger Hinweis: Falls man im WP-Wurzelverzeichnis eine php.ini hat, muß diese ebenfalls mit in das /kontakt/-Verzeichnis kopiert werden, denn im Unterschied zur .htaccess werden die dort gemachten Einstellungen nicht auf Unterverzeichnisse „vererbt“.

4 Kommentare »

Der Haken am Trick

Vor einiger Zeit hatte ich das 123 IIS Permalink-Plugin vorgestellt. Durch Kommentare zum 123 No Rewrite Permalink-Plugin wurde ich auf ein Problem aufmerksam gemacht, welches sich auch beim IIS auswirkt. Erfreulicherweise kann man das beim IIS im Unterschied zum Apache-Server wieder ausbügeln, da hier die POST-Daten nicht verloren gehen.

So gibt es nun also eine neue Version 0.11 des 123 IIS Permalink-Plugins, die auch mit Datenübergabe per POST oder GET funktioniert. Nebenbei habe ich gleich noch eine permanente Weiterleitung (301) der alten ‚/index.php/irgendwas‘-Aufrufe eingebaut. So braucht man sich wegen alter Permalinks z.B. bei Google keine Sorgen zu machen.

0 Kommentare »