HTML_AJAX aus dem PEAR-Framework mit JsMin zu schlankerem JavaScript Code optimieren

Im Ferienhauskatalog von Location Bretagne nutzen wir eine typische LAMP-Installation. Einige Funktionen des Katalogs (bspw. die Geo-Suche) werden durch AJAX-Technologien unterstützt, die das HTML_AJAX Paket aus dem PEAR-Framework nutzen. Dieses Paket wird entwickelt und unterstützt von Elizabeth Smith, David Coallier, Joshua Eichhorn (er stellt auch eine gute Dokumentation bereit), Laurent Yaish und Arpat Ray.

Insgesamt finde ich das Paket sehr gelungen und auch nutzbar, obwohl es leider seit 16.6.2008 im Beta-Stadium (0.5.6) „verharrt“. Dafür steht es unter eine L-GPL Lizenz und lässt sich als Bestandteil von PEAR bequem mit dem PEAR-Installer installieren und updaten. Zusammengefasst lassen sich mit HTML_AJAX PHP-Funktionen und Klassenmethoden als AJAX-Funktionen registrieren, so dass der PHP-Code komfortabel als JavaScript-Code bereitgestellt wird und sich so bequem aus JavaScript aufrufen lässt.

Einen gravierenden Nachteil hat das Paket jedoch: Der generierte JavaScript-Code ist alles andere als „kompakt“. Zwar lässt sich der Code mit gzip komprimieren, doch führt dies dennoch regelmäßig zu schlechten Bewertungen mit YSlow! oder Google Page Speed. Folgender Beispielcode zeigt, wie die Kompression mit gzip aktiviert wird:

//a session is required(you can also set session.auto_start=1 in php.ini)
session_start();
include ‚HTML/AJAX/Server.php‘;
$server = new HTML_AJAX_Server();
// activate gzip compression
$server->compression[‚enabled‘] = true;
$server->handleRequest();

Ein Ausweg ist die Aktivierung von „packJavaScript“, die wie folgt aktiviert wird:

//a session is required(you can also set session.auto_start=1 in php.ini)
session_start();
include ‚HTML/AJAX/Server.php‘;
$server = new HTML_AJAX_Server();
// activate gzip compression
$server->compression[‚enabled‘] = true;
// activate pack javascript
$server->ajax->packJavaScript = true;
$server->handleRequest();lan

Dadurch wird der Code schon deutlich kompakter, da überflüssige Zeilenumbrüche etc. weggelassen werden. Die Testergebnisse bei YSlow! und Page Speed werden besser, allerdings sind sie noch lange nicht optimal. Statt dessen zeigte Page Speed bei mir immer noch mögliche Verbesserungsraten von ca. 1/3 an. Doch wie können wir den Code noch kompakter und schlanker machen? Standardmäßig leider gar nicht, statt dessen sind Modifikationen am HTML_AJAX Paket notwendig.

Mein Ansatz besteht darin, die Bibliotheken JsMin für PHP von Ryan Grove bzw. die nochmals optimierte Version JsMin+ für PHP von Tino Zijdel in den „Packalgorithmus“ von HTML_AJAX zu integrieren. Dafür habe ich die Methoden packJavascript aus dem HTML_AJAX Paket (Klassenname: AJAX.php) insoweit modifiziert, dass nun über die zusätzliche öffentlich verfügbare Objekteigenschaft packJavaScriptEngine ausgewählt werden kann, mit welchem Mechanismus der JavaScript Code optimiert werden soll. Dabei muss als Stringparameter einer der folgenden Werte angegeben werden ORIGINAL, JSMIN oder JSMIN+.

In ersten Tests funktionierte die modifizierte Version problemlos. Die Nutzung von JsMin erzeugte nochmals deutlich kompakteren JavaScript Code, so das die Testresultate von YSlow! oder Google Page Speed immerhin „grün“ wurden. Allerdings wurde noch immer bemängelt, dass der JavaScript Code noch kompakter sein könnte. Die Nutzung von JsMin+ brachte dann die erhoffte „Erlösung“: Der Code wird derart kompakt, dass bei Tests nichts(!) nichts mehr zu bemängeln haben.

Den beispielhaften Aufruf meiner modifizierten Version unter Nutzung von JsMin+ zeigt folgender Beispielcode (dabei muss die Bibliothek jsmin.php bzw. jsminplus.php seperat eingebunden werden – beide Bibliotheken können kostenlos auf den Seiten der Autoren geladen werden):

// jsminplus.php must be required because it’s not provided by HTML_AJAX!
require_once ‚jsminplus.php‘;

$server = new HTML_AJAX_Server();
$server->compression[‚enabled‘] = true;
$server->ajax->packJavaScript = true;
// Use JsMin+ to compact JavaScript
$server->ajax->packJavaScriptEngine = ‚JSMIN+‘;
$server->handleRequest();

Die modifizierte Version von AJAX aus dem PEAR-Paket HTML_AJAX kann hier heruntergeladen werden. Ich habe die Modifikation ebenso wie die Originalautoren unter eine LGPL Lizenz gestellt.

Über Kommentare, Verbesserungsvorschläge und Anregungen freue ich mich sehr!!

/**
* Makes JavaScript code smaller, using 3 possible engines: JsMin for PHP, JsMin+ for PHP or the orginial one provided by the authors of HTML_AJAX
*
* @param string $input Javascript to pack
*
* @access public
* @return string packed javascript
*/
function packJavaScript($input) {
switch($this->packJavaScriptEngine) {
case ‚JSMIN‘:
return JSMin::minify($input);
break;
case ‚JSMIN+‘:
return JSMinPlus::minify($input);
break;
default:
return $this->_packJavaScript($input);
}
}
/**
* Make JavaScript code smaller
*
* Currently just strips whitespace and comments, needs to remain fast
* Strips comments only if they are not preceeded by code
* Strips /*-style comments only if they span over more than one line
* Since strings cannot span over multiple lines, it cannot be defeated by a
* string containing /*
*
* @param string $input Javascript to pack
*
* @access private
* @return string packed javascript
*/
function _packJavaScript($input)
{
$stripPregs    = array(
‚/^\s*$/‘,
‚/^\s*\/\/.*$/‘
);
$blockStart    = ‚/^\s*\/\/\*/‘;
$blockEnd      = ‚/\*\/\s*(.*)$/‘;
$inlineComment = ‚/\/\*.*\*\//‘;
$out           = “;
$lines   = explode(„\n“, $input);
$inblock = false;
foreach ($lines as $line) {
$keep = true;
if ($inblock) {
if (preg_match($blockEnd, $line)) {
$inblock = false;
$line    = preg_match($blockEnd, ‚$1‘, $line);
$keep    = strlen($line) > 0;
}
} elseif (preg_match($inlineComment, $line)) {
$keep = true;
} elseif (preg_match($blockStart, $line)) {
$inblock = true;
$keep    = false;
}
if (!$inblock) {
foreach ($stripPregs as $preg) {
if (preg_match($preg, $line)) {
$keep = false;
break;
}
}
}
if ($keep && !$inblock) {
$out .= trim($line).“\n“;
}
/* Enable to see what your striping out
else {
echo $line.“
“;
}//*/
}
$out .= „\n“;
return $out;
}
Share

Page Speed: Google möchte schnellere Webseiten…?

Mit Interesse habe ich den Beitrag im „Official Google Blog“ über den Wunsch Googles, dem Nutzer schnellere Webseiten zu bieten, gelesen. Im Beitrag „Let’s make the Web faster“ schreiben Urs Hoelzle und Bill Coughran über ihre Ideen, die Ladezeit von Webseiten zu reduzieren, um den „Surfer“ ein schnelleres „Surf-Erlebnis“ zu ermöglichen. Diesen Ansatz untermauern beide noch durch ein eigens dafür gedrehtes Video. Praktischerweise verweisen sie noch auf eine eigens für diese Anliegen produzierte Seite (http://code.google.com/intl/de-DE/speed/), von der unter anderem das mittlerweile recht bekannte Tool YSlow! sowie das neuere Google Page Speed (beides Plugins für die Firefox-Extension Firebug) und diverse weitere heruntergeladen werden können.

Das Tool Google Page Speed ist neu für mich, mit dem Tool YSlow habe ich ja bereits einige Erfahrungen sammeln können. In einem ersten Test zeigte Google Page Speed (ich habe die Version 1.0.1.1 Beta genutzt) auch einige Empfehlungen, die ich von YSlow! nicht bzw. nicht in dieser Form erhalten habe, darunter:

  • Detailliertere Empfehlungen zur Kompression von Bildern,
  • die Empfehlung unterschiedliche Hostnamen zur Beschleunigung des gleichzeitigen Ladens externer Ressourcen,
  • die Empfehlung, bestimmte Elemente (Bilder, CSS) von „Cookie-losen“ Domains zu laden,
  • detailliertere Empfehlungen zur Beschleunigung von CSS-Stylesheets,
  • detailliertere Empfehlungen zur „richtigen Lade-Reihenfolge“ externer Dateien.

Spannend fand ich an den Ergebnissen, dass offensichtlich auch die JavaScripts der „hauseigenen“ Dienste Google-Maps und Google Analytics, die wir bspw. für die Satelliten-Geo-Suche auf www.location-bretagne.de nutzen, noch optimierungsbedürftig sind (siehe Abbildung)… 😉 Also, Google, ran! Ich möchte bei Euren eigenen Diensten einen Optimierungsgrad von 100% sehen.

Google Page Speed Ergebnisse einer Seite mit Google Maps

Share