PHP-Klasse staticfiles

Einleitung
Voraussetzung
Installation
Debugging
Komplettes Beispiel
Dokumentation

Einleitung

Mehrere Dateien im Header (oder allgemein in der Seite) einzubinden bedeutet: der Webbrowser des Besuchers meiner Webseite muss mehr Requests absetzen, bevor er die Seite anzeigen kann.

Ja das kann doch aber minimieren! Die Suchmaschine deiner Wahl liefert mit den Begriffen compress oder minify und css oder js so einige weiterhelfende Treffer.

Und die nachfolgende Klasse ist meine Lösung...
Meine Klasse staticfiles macht im ersten Schritt Folgendes:
  • sie nimmt alle js und css Dateien entgegen
  • Die Javascripts und CSS Dateien werden zu je einer Datei zusammengefasst. Bei CSS-Dateien werden die ggf. enthaltenen relativen Verweise zu Referenzen mit absolutem Pfad umgeschrieben.
  • unnötige Leerzeichen, Tabs etc. werden entfernt
  • Die zusammengefassten (germergten) Dateien werden als Cachedatei abgelegt. Eine Caching Logik aktualisiert den Cache, sobald die Caching-Zeit abgelaufen ist und sich eine der eingebundenen Dateien geändert hat.
  • Ausgegeben wird im Html-Dokument die Verlinkung zum Cachefile

Seitenanfang


Voraussetzung

  • PHP 5
  • Javascript- und Stylesheet-Dateien sind am eigenen Webserver
  • Pfade zu Javascript- und Stylesheet-Dateien erfolgt mit absolutem Pfad
  • Zugriff auf Webserver-Konfiguration zum Aktivieren der gzip Kompression (beim Apache reicht es auch, wenn .htaccess erlaubt ist)

Seitenanfang


Installation

Download

staticfiles_class_php.zip (18 kB)

Auspacken

Kopieren Sie die Datei staticfiles.class.php in ihr PHP-Verzeichnis. Sie kann auch in einem beliebigen Unterordner abgelegt werden.

Einbindung in deine Webseite

(1)
In deiner PHP-Datei, die den HTML-Header ausgibt, ist die Klasse einmalig einzubinden:

 require_once("/php/staticfiles.class.php");
 $o=new Staticfiles();
PHP: staticfiles - Initialisierung


(2)
Es gibt 2 Funktionen, mit denen Javascript- und CSS-Dateien hinzugefügt werden.
Javascript:

 $o->addJs([JS-Dateiname]);
 oder
 $o->addJs([JS-Dateiname], "defer");
PHP: staticfiles - Javascript-Datei hinzufügen


... und die CSS-Dateien:

 $o->addCss([CSS-Dateiname]);
 oder aber
 $o->addCss([JS-Dateiname], [Media-Attribut]);
PHP: staticfiles - CSS Datei hinzufügen


(3)
Die Cachefiles, die alle Dateien zusammenfassen zu erzeugen und die Ausgabe der Links für den HTML-Header erfolgt mit

 $o->writeMedia("js");
 $o->writeMedia("css");
PHP: staticfiles - Cachedatei erzeugen und HTML-Code ausgeben

Gzip-Kompression und Caching am Client

Es gibt in der Klasse zwar eine Funktion zur Komprimierung des Codes. Diese entfernt überflüssige Tabs und Leerzeichen. Dies spart ca. (lächerliche) 2% des Codes ein. Dies lässt sich um ca. 70..80% drücken, wenn man die gzip-Kompression auf dem Webserver für .css und .js Dateien aktiviert.

Eine zweite am Webserver notwendige Einstellung ist das Caching am Client. Dies legt fest, wie lange ein Webrowser eine einmal abgerufene Datei im Browsercache festhalten soll.

Apache
Nachfolgender Code gilt für den Apache Webserver.

# gzip Kompression einschalten:
mod_gzip_on Yes

# Client-Cache aktivieren
ExpiresActive On

### 2 days im Browsercache belassen
ExpiresByType application/x-javascript "access plus 2 days"
ExpiresByType application/javascript "access plus 2 days"
ExpiresByType text/css "access plus 2 days"
Apache Konfiguration; Auszug

Nginx
... oder für Nginx:
Die Kompression kann man global für alle Webs in der Server-Sektion einschalten.

# gzip Kompression einschalten:
gzip             on;
gzip_types       text/css text/javascript;
Nginx Konfiguration; Auszug


Das Expire lässt sich im im virtuellen Host setzen.

location ~ \.(css|js)$ {
    (...)
    # Client-Cache aktivieren
    expires       2d;
}
Nginx Konfiguration; Auszug


Seitenanfang


Debugging

In der eigenen Entwicklungsumgebung braucht man zumeist die Originaldateien im Zugriff. Bei dieser Klasse kann man sowohl Debugging-Informationen einschalten als auch die Original-Dateien einbinden.
Die Debug Informationen erscheinen im HTML-Code als HTML-Kommentar.

In meiner Entwicklungsumgebung heissen die Hosts local.[domainname] - das fange ich per Matching auf $_SERVER["SERVER_NAME"] ab.

require_once("/php/staticfiles.class.php");
$o=new Staticfiles();

// Test, ob ich in der Entwicklungsumgebung bin
if (strpos($_SERVER["SERVER_NAME"], "local.")===0) {
    $o->setDebugDefaults(); // schaltet Debug Infos ein
    $o->setMerging(false);  // schaltet Merge aller Dateien aus und bindet Links zu Originalfiles ein
}

// hier geht es weiter mit addJS und addCss ...
PHP: Debugging aktivieren und Originaldateien verwenden


Seitenanfang


Komplettes Beispiel

Ausgangslage: CSS-Dateien und Javascripts sind im Header des HTML-Dokuments:

<!DOCTYPE html>
<html>
    <head>
        ...
        <!-- Stylesheets -->
        <link rel="stylesheet" type="text/css" href="/javascript/DataTables-1.7.6/media/css/demo_table.css" media="screen"></link>
        <link rel="stylesheet" type="text/css" href="/javascript/DataTables-1.7.6/media/css/demo_page.cs" media="screen"></link>
        <link rel="stylesheet" type="text/css" href="/javascript/fancybox/jquery.fancybox-1.3.4.css" media="screen"></link>
        <link rel="stylesheet" type="text/css" href="/css/meine_basisklassen.css" media="screen"></link>
        <link rel="stylesheet" type="text/css" href="/css/mein.css" media="screen"></link>
        <link rel="stylesheet" type="text/css" href="/css/drucker.css" media="print"></link>
        ...
        <!-- Javascripts -->
        <script type="text/javascript" src="/js/jquery-1.4.3.min.js"></script>
        <script type="text/javascript" src="/js/jquery.mousewheel-3.0.4.pack.js"></script>
        <script type="text/javascript" src="/js/jquery.fancybox-1.3.4.pack.js"></script>
        <script type="text/javascript" src="/js/DataTables-1.7.6/media/js/jquery.dataTables.min.js"></script>
        <script type="text/javascript" src="/js/meine-eigenen-funktionen.js"></script>
        ...
    </head>
    ...
</html>
HTML-Beispiel-Header mit mehreren Javascript- und CSS-Dateien


Statt der Link- und Script-Tags werden die Methoden zum Hinzufügen angewendet. Mit writeMedia erfolgt die Ausgabe:

<html>
    <head>
        ...
        <?php

         // Klasse laden und Objektinstanz erzeugen
         require_once("/php/staticfiles.class.php");
         $o=new Staticfiles();

         // CSS hinzufuegen
         $o->addCss("/javascript/DataTables-1.7.6/media/css/demo_table.css");
         $o->addCss("/javascript/DataTables-1.7.6/media/css/demo_page.css");
         $o->addCss("/javascript/fancybox/jquery.fancybox-1.3.4.css");
         $o->addCss("/css/meine_basisklassen.css");
         $o->addCss("/css/mein.css");

         $o->addCss("/css/druckausgabe.css", "print");

         // Javascripts hinzufuegen
         $o->addJs("/js/jquery-1.4.3.min.js");
         $o->addJs("/js/jquery.mousewheel-3.0.4.pack.js");
         $o->addJs("/js/DataTables-1.7.6/media/js/jquery.dataTables.min.js");
         $o->addJs("/js/meine-eigenen-funktionen.js");

         // Ausgabe als HTML (Mergen und Kompression werden im Hintergrund ausgefuehrt)
         $o->writeMedia("css");
         $o->writeMedia("js");
       ?>
       ...
    </head>
    ...
</html>
PHP: komplettes Code-Beispiel für Einsatz der Klasse staticfiles


Die Funktionen writeMedia erzeugen/ aktualisieren im Hintergrund die Cachefiles und im Vordergrund wird diese Ausgabe erzeugt:

<link rel="stylesheet" type="text/css" href="/~cache/css_cache_screen_[...].css" media="screen"></link>
<link rel="stylesheet" type="text/css" href="/~cache/css_cache_print_[...].css"  media="print"></link>
<script type="text/javascript" src="/~cache/js_cache_execution_[...].js"></script>
HTML-Auszug: Ausgabe der writeMedia Funktion


Seitenanfang


Dokumentation

Class: staticfiles
Methoden verstecken

public __construct()

init function; it sets defaults.
@return bool (dummy)
public setDefaults()

set all vars to initial values
@return bool (always true)
public setDebugDefaults()

set debug default settings
@return bool (always true)
public setMinCacheTime( $int) ... all param(s) required

set minimum cachetime on server for merged js and css files
@param integer value in seconds
@return boolean
public setDebug( $bool) ... all param(s) required

set debug flag (for development environment)
@param boolean set true to enable debug output
@return boolean
public setMerging( $bool) ... all param(s) required

set merge flag (for development environment)
@param boolean set false to disable the generation of merged cachefiles
@return boolean
public setRewriteCache( $bool) ... all param(s) required

set flag bRewriteOnEachRequest (for development environment)
@param boolean set true to ignore caching time
@return type
public setCacheBase( $str) ... all param(s) required

set another basepath (behind webroot)
@param string new basepath
@return boolean
public setCacheDir( $str) ... all param(s) required

set another cache directory.
@param string new basepath (below webroot)
@return boolean
public getMinCacheTime()

get current caching time on server
@return integer
public getDebug()

get current debug flag
@return boolean
public getMerging()

get current merge flag
@return boolean
public getRewriteCache()

get current flag to rewrite the cache
@return boolean
public getCacheBase( $str) ... all param(s) required

get current basepath of cache
@return boolean
public getCacheDir( $str) ... all param(s) required

get full path of current cache directory
@return boolean
private getStats( $sOrig, $sCrunched, $sCommment) ... all param(s) required

show some statistics info about code compression an gzip
@param type $sOrig
@param type $sCrunched
@param type $sCommment
@return type
private log( $s) ... all param(s) required

write logging information (only if debug is enabled)
@param type $s
@return type
public addMedia( $sType, $aFiledata) ... all param(s) required

add media file to array; it is called by addJs() and addCss()
@param string $sType one of css|js
@param array $aFiledata; Keys: file: filename; other: attributes
@return type
private genHtml( $sType, $aFile) ... all param(s) required

generate html code to link the cachefile (or original files if cache is disabled)
@param string $sType type; one of css|js
@param array $aFile array with filedata (keys are attributes)
@return string html code
public writeMedia( $sType) ... all param(s) required

merge original files of a group to a cachefile. It updates or just
touches the cachefile.
@param string $sType one of css|js
@return bool (dummy)
public addJs( $sFile, $defer = 'execution') ... 1 of 2 param(s) required

add a js file to the js array
@param string $sFile file to load
@param string $sDefer
@return type
public compressJs( $s) ... all param(s) required

compress js code
@param string $s js code
@return string with new js code
public rewriteCss( $s, $sFile) ... all param(s) required

rewrite urls in css data; this function finds relative
pathes and rewrites them to absolute pathes
@param string $s css content
@param string $sFile filename of included css (to detect the "current" path)
@return string the reswritten css code
public compressCss( $s) ... all param(s) required

compress css code: remove spaces, tabs, line breaks
@param string $s css data
@return string rewritten css data
public addCss( $sFile, $sMedia = 'screen', $sTitle = '') ... 1 of 3 param(s) required

add a css file to this object
@param string $sFile path and filename of css file like in href attribute
@param string $sMedia media type
@param title $sTitle title (will be ignored so far)
@return bool (dummy)
Properties verstecken

private $aStatic = Array

configuration array
@var array
public $sCacheBase = /~cache/

name for basepath behind webroot
@var string
public $sCacheDir = false

absolute path of cache directory; it will be set in the method
setDefaults to [document root]/$this->sCacheBase/
@var string
public $iMinCacheTime = 3600

minimum time to cache js and css cachefile on server - even one of the
source files have been changed.
@var integer
public $bDebug = false

flag: show debug output? If it is true then you see the merged files,
replacements and statistic data in the html header section (as comment)
@var boolean
public $bMerging = false

flag: merge files into a cachefile? If it is false then the source
files will be used. This is helpful in the development environment to
debug code with original files.
@var boolean
public $bRewriteOnEachRequest = false

flag: overwrite cachefile on each request?
You can use it in your development environment. It overrides the setting
of $this->iMinCacheTime and regenerates merged cachefiles on each request.
debug code with original files.
@var boolean

Seitenanfang