Bernhard Häussner
Tags: Artikel mit dem Tag «Codesnippets» durchstöbern

Howto: Alleinstehende Unds für XHTML umwandeln

16.04.2009, 13:22
$text=preg_replace ('/&(?!amp;|quot;|nbsp;|gt;|lt;|laquo;|raquo;|copy;|reg;|#[0-9]{1,5};|#x[0-9A-F]{1,4};)/','&', $text);

In meinem Markup-Parser für diesen Blog hatte ich das Problem, dass ich zwar einzelne & in &amp; umwandeln konnte, damit ich Et-Zeichen im ganz normalen Text schreiben kann, auf der anderen Seite aber auch HTML <tags> erlauben will. Wenn ich jetzt aber über HTML schrieben will, muss ich ja auch irgendwie die größer und kleiner-Zeichen encodieren, damit nicht alles einfach vom Browser gerendert wird. Wenn ich aber ein &lt; eingebe, würde das Kaufmanns-Und sofort zu &amp; umgewandelt und so würde dann im Quelltext &amp;lt; stehen und im Text nicht < sondern &lt;. Also brauchte ich eine Methode um nur einzelne kaufmännische Unds zu finden. Das lief dann auf obigen Regulären Ausdruck hinaus.

Er ersetzt & mit &amp; nur dann, wenn dahinter keines der HTML-Entities folgt. Da es eine sehr lange Liste von benannten HTML-Entities gibt, habe ich nur die aufgenommen, die man in HTML Umwandeln muss („htmlspecialchars“), damit ihre Bedeutung erhalten bleibt und ein paar Sonderzeichen, die ich sonst nie finde. Alles andere (z.B. &eacute; für é, 文字, ...) wird ja von UTF-8 abgedeckt. Für ASCII kann man auch noch die dezimale oder hexadecimale Unicode-Notierung verwenden.

Der regexp verwendet eine Erweiterung, die Negative Vorausschau (?!x). Das ist so etwas wie ein Unter-Ausdruck, der zwischendurch überprüft wird am Text nach der aktuellen Position. Die Buchstaben, die auf den überprüften Ausdrück passen, werden nicht mit "gefressen", sie werden also nicht übersprungen, sondern nur kurz getestet. Nur wenn der Ausdruck nicht zutrifft wird von der Ursprungsposition weiter getestet. Es gibt natürlich auch noch positive Vorausschau (?=x) (die weiter laufen lässt, wenn der Ausdruck passt), sowie positive (?<=x) und negative (?<!x) Zurückschau (die jeweils den Text vor der aktuellen Position prüfen).

Das würde zum Beispiel alle Minuskeln ausgeben, die nach einem „o“ stehen: [a-z](?<=o.). Man beachte den Punkt nach dem „o“. Er steht für das gerade überlaufene Zeichen für das jetzt geprüft wird was (von der aktuellen Position hinter dem Zeichen aus gesehen) davor steht. Das bedeutet in der Rücksicht sieht sich das Zeichen nochmal selbst. Noch ein Beispiel: .(?<=o(?#comment).{5}) findet alle Zeichen 5 Positionen vor „o“.

Diese Features stehen in Ruby übrigens nur teilweise zur Verfügung.

Kommentare: keine

Schöne URLs dank mod_rewrite

01.03.2009, 13:17
blogjournal.php?page=2 => blog/journal/2                   (22->14;64%)
blogtags.php?tag=PHP&page=2 => blog/tags/PHP/2             (27->15;56%)
blogentry.php?link=1_Hello_World! => /blog/1_Hello_World!  (33->20;61%)

Eigentlch war das ja schon lange geplant, alle URLs etwas zu verschönern, und sämtliche überflüssige .php?bla=&foo= rauszunehmen. Doch ich hatte immer das Problem, dass die alten URL nicht mehr benutzbar waren. Das ganze habe ich erst versucht mit RewriteRules zu lösen, doch es hat sich herausgestellt, dass es mit PHP leichter zu lösen ist. Wie alles funktioniert will ich hier kurz beschrieben.

Wer den RSS-Feed liest, dem ist vielleicht aufgefallen, dass über Nacht ein paar viele neue Einträge dazu gekommen sind. Diese sind leider gar nicht neu, jedoch da ich das URL-Format ändern musste, werden sie als neu erkannt. Die Seite hat jetzt URL-mäßig einen schönen hierarchischen Aufbau:

/
/about
/blog
/blog/1_Hello_World!
/blog/[...alle Einträge]
/blog/archiv
/blog/feeds
/blog/journal
/blog/journal/1
/blog/journal/2
/blog/journal/[...alle Seiten]
/blog/newcomments
/blog/tags
/blog/tags/PHP
/blog/tags/PHP/1
/blog/tags/PHP/2
/blog/tags/PHP/[...alle Seiten]
/blog/tags/[...alle Tags]
/contact
/projects
/projects/1_Mein_Blog

Das alles wird erstmal von mod_rewrite erledigt. Die URLs oben werden in PHP-verträgliche URLs mit GET-Paramtern usw. umgewandelt. Damit dann aber nicht immer Seiten doppelt erscheinen, musste ich im PHP-Script überprüfen, durch welche URL das Script aufgerufen wurde. Stimmt diese nich mit der kanonischen URL überein, dann leitet das Script mittels eines 301-Redirects direkt an diese weiter. So ist jedes Dokument nur einmal vertreten, was sowol meinen Aufrufstatistiken zuvorkommt, Verwirrung bei Benutzern vorbeugt und Suchmaschinen zufrieden stellt.

Außerdem sind die URLs nicht mehr von der Technik hinter den Kulissen abhängig. Sollte ich also irgendwann die Technik von PHP auf ColdFusion, ASP, Java oder was es alles gibt umstellen, bleiben die URLs (höchstwahrscheinlich) gleich. Sie enthalten keine sinnlosen Dateiendungen usw. Der Prozess funktioniert so:

                           |
                           V
              Request mit beliebiger URL
                           |
                           V
Apaches mod_rewrite wandelt in „normale“ URL mit GET Parametern um
                           |
                           V
    PHP parst die URL und entschiedet, was angezeigt werden soll
                           |
                           V
 PHP vergleicht die kanonische URL zur Anzeige mit der des Requests
             /                          \
            /                            \
    URL ist gleich                   URL ist anders
           |                              |     
           V                              V
  Content wird angezeigt         301 an die richtige URL

Im PHP sieht das Vergleichen dann ungefähr so aus: (z.B. in blog.php)

function setCanURL($root,$url) { // Leiter weiter, falls nötig
	$request_url_withoutHTTP=$_SERVER['REQUEST_URI'];
	$canonical_url_withHTTP=$root.$url;
	$canonical_url_withoutHTTP=removeDomain($root.$url);
	$request_url_withoutHTTP_realspaces=rawurldecode($request_url_withoutHTTP);
	if ($request_url_withoutHTTP_realspaces!=$canonical_url_withoutHTTP) {
			redirect301($canonical_url_withHTTP);
	}
}
function redirect301 ($newurl) { // Macht 301 Weiterleitungen
	header("HTTP/1.1 301 Moved Permanently"); 
	header("Location: $newurl"); 
	header("Connection: close");
	die();
}
function removeDomain($url) { // gibt die URL ohne den Domaine-Teil zurück
	$url=preg_replace('/https?:\/\/([0-9a-zA-Z]+\.){1,}([0-9a-zA-Z]+)\//','/',$url);
	return $url;
}
setCanURL('http://localhost/testseite/','blog');

Man muss natürlich immer irgendwie wissen, wie die kanonische URL aussehen soll. Dann ruft man einfach die Funktion auf. Es ist egal, wie die alte URL aussah! Am besten noch da einbauen, wo die URLs geparst werden bevor die Seite gerendert wird.

Super-Geeky Firefox Quicksearch feature

Die neuen URLs machen auch etwas sehr Zeitsparendes möglich. Empfiehlt sich bei allen Seiten zu machen, die man häufig benutzt (und man kurze URL-Pfade besucht):

In Firefox erstellt man im Bookmark-Manager ein neues Bookmark mit Folgenden Eigenschaften:

  • Adresse: http://bernhardhaeussner.de/%S (Großes S)
  • Schlüsselwort: bh

Allgemein funktioniert das so, dass man z.B. für Suchfunktionen „[Schlüsselwort] [Begriff]“ in die Adresszeile eingeben kann, und so eine Schnelle Suchfunktion hat. Da Firefox aber nichts anderes macht, als %S mit dem Begriff zu ersetzten, kann man das auch für jede andere URL verwenden. So kann ich jetzt durch Eingabe von bh blog direkt zu meinem Blog kommen. Sehr praktisch... Übrigens, benutzt man den Kleinbuchstaben %s wird / zu %2F und ähnliches, wodurch man nicht alle URLs eingeben kann, was jedoch in GET-Parametern wichtig ist („urlencode“).

Super-Geeky Konqueror Quicksearch feature + KRunner

Im Konqueror gibt es auch eine Suche über die Adressleiste, die sich Webkürzel nennt. Man kann diese Webkürzel in Konqueror einrichten im Einrichtungsdialog unter Webkürzel. Dort gibt man dann als Adresse http://bernhardhaeussner.de/\{@} ein und als Kürzel z.B. bh, bxt.

Selbst wenn man Konqueror nicht benutzt, lassen sich diese Kürzel in KRunner benutzten: Ein Tastendruck auf ALT+F2 und die Eingabe von bh:blog führt dann also direkt zu meinem Blog. Ziemlich praktisch und lässt sich auch beliebig erweitern.

Zum Glück ist meine Seite auch noch nicht überall verlinkt, weshalb ich auch sonst nicht viel ändern muss.

Kommentare: keine

Weniger Traffic durch JS, PNG und CSS optimierung

01.02.2009, 18:46
Web Compression

Web Compression

Wie erreiche ich schnellere Ladezeiten für meine Webseiten ohne ein riesiges Rechenzentrum anzumieten? Man kann mit einigen Details schon unglaublich viel sparen, denn schon kleine Veränderungen an häufig angeforderten Dateien machen viel aus. Das Aktivieren von gzip, das Komprimieren von HTML, CSS und Javascript, die Optimierung von PNG-Bildern und das Verwenden von CSS-Sprites und CDNs.

CSS-Sprites

Anstatt jedes Icon und jedes Hintergrundbildchen in einer eigenen Datei zu laden, werden alle in ein Bild gepackt. Da die meisten Besucher ohnehin einen Breitbandanschluss haben, machen für sie wenige KB Dateigrößen-Unterschied kaum etwas aus. Doch viele Requests brauchen bei jeder Verbindung viel Zeit. Für jedes Bild, dass man mit einem anderen Kombinieren kann, spart man ein Request.

Damit man nicht viele Container-Elemente ins HTML einbauen muss, lohnt es sich die Bilder geschickt zu kombinieren. Ich habe so auf meiner Homepage das Markup kein bisschen verändert, als ich vor kurzem CSS-Sprites implementiert habe. Um die Bilder zu packen, setzt man z.B. solche Muster und Verläufe, die horizontal wiederholt werden, zusammen untereinander in ein Bild und solche, die vertikal wiederholt werden, nebeneinander in ein anderes. Buttons und Ähnliches, was ohne Wiederholung gerendert wird, kann man entweder in ein einzelnes Bild geben oder sie in eines der beiden anderen einbauen.

Auf dieser Seite habe ich z.B. die kleinen Icons ganz rechts in die Kombinierte Graphik gestellt, damit links davon noch ein Bild mit fester Größe Platz findet. Außerdem sind unter dem Sprechblasen-Icon für Kommentare nur transparente Pixel, sodass in längeren Kommentaren keine anderen Hintergrundbilder auftauchen. Der Webseitenhintergrund ist gesondert als JPEG abgespeichert, da er keine Transparenz benötigt und so viel kleiner ist.

Komprimieren von Javascript, CSS und HTML

Das Komprimieren der eigentlichen Webseite ist auch nicht schwer. Da die Webseite sowieso dynamisch erstellt wird, lasse ich einfach sämtlichen zusätzlichen Whitespace im HTML weg. In den Templates bleibt alles schön übersichtlich, aber was gesendet wird, ist rund 10% kleiner.

Deutlich interessanter wird das ganze bei Javascript: Da Javascripts meistens statisch sind, habe ich mit ein einfaches Shell-Script geschrieben, welches alle Javascript-Dateien in eine Datei zusammenhängt um Reqests zu sparen und mit JSMin den Whitespace und Kommentare entfernt. So wird bei mir aus 19 kommentierten und nach Zweck getrennten Dateien mit rund 90 KB eine einzige mit 56 KB, also mit 30% Einsparung eine effektive Methode. Am einfachsten lässt es sich natürlich sparen, wenn man auf einiges an Javascript verzichtet.

#!/bin/sh
# Sammle alle js
for file in js/*; do
 cat "$file" >> javascript.js
 echo >> javascript.js # Leerzeile zwischen Scripts
done
./jsmin <javascript.js >>javascript.min.nocp.js # komprimieren
cat jslicences.txt javascript.min.nocp.js > javascript.min.js # Lizenzen hinzufügen
rm javascript.min.nocp.js

Beim CSS gilt ähnliches: Man kann alles in eine Datei packen und Whitespaces entfernen, jedoch habe ich keine automatische Komprimierung gefunden. Was man auf diversen Webseiten findet, spart normalerweise 10-20%.

PNG-Optimierung

Mit verlustfreier Komprimierung und trotzdem großer Farbpalette hat das PNG-Format Vorteile, wenn es um Icons und Graphiken geht. Doch aus der verlustfreien Komprimierung lässt sich noch mehr heraus kitzeln, indem man brute-force-mäßig die besten Kompressionsparameter verwendet. Das macht z.B. das einfach zu bedienende optipng und spart damit auch nochmal bis zu 15%.

CDN

Ein Content Delivery Network wird eher für besondere Seiten rentabel: Für Seiten mit viel statischem Content, also Bildern oder Videos. So entlastet man nicht nur den eigenen Server mit dem dynamischen Inhalt, sondern verteilt den Content über den ganzen Globus, sodass er dann nicht mehr so weit verschickt werden muss.

Für alle Seiten, die jQuery verwenden, ist es möglich sich dieses von Googles CDN hosten zu lassen. Dazu verwendet man einfach statt der URL der Javascript-Datei auf dem eigenen Server folgende: http://ajax.googleapis.com/ajax/libs/jquery/1.3.1/jquery.min.js und schon spart man sich wieder einige KB pro Seitenaufruf. Und auch die User sparen sich diese meistens. Da nämlich inzwischen sehr viele Seiten jQuery bei Google hosten, haben die meisten Surfer diese Datei schon im Cache des Browsers, müssen sie also nicht mehr herunterladen.

Kommentare: 3 Einträge
« Vorherige Seite [ Seite 1 2 3 4 5 ]
 
Χρόνογραφ
© 2008-2017 by Bernhard Häussner - Impressum - Login
Kurz-Link zur Homepage: http://1.co.de/