Externe Dateien in Silverstripe mit Requirements zusammenfassen

Eintrag von Sascha Köhler am 09.03.2010; 0 Kommentare.

Inhaltsverzeichnis

Ladezeit reduzieren durch Zusammenfassen von externen Dateien

Wenn man mehrere CSS- oder Javascriptdateien auf einer Webseite benutzt, kann die Performanz der Seite erhöht werden, indem diese Dateien typweise in eine große Datei kombiniert werden. Diese Technik ist auch unter dem englischen Namen "suturing" bekannt, was aus dem englischen Medizinwortschatz entlehnt ist und in etwa "(zusammen)nähen" bedeutet.

Als Beispiel wird im nachfolgenden Artikel die Einbindung der Stylesheets auf dieser Webseite beschrieben.

Auf der www.standardized.de werden aktuell drei Stylesheets verwendet:

  • reset.css
  • base.css
  • tipTip.css

Um diese getrennt zu laden, müsste der Browser drei Anfragen an den Webserver schicken. Da die Dateien sehr klein sind, dauert das Stellen der Anfragen länger als die eigentliche Auslieferung. Außerdem kann der Benutzer das Verbindungslimit für Anfragen an die gleiche Domain erreichen, wenn es noch viele andere Objekte zu laden gibt (z.B. Javascripte und Bilder). Durch das Zusammenfassen der Dateien zu einer werden diese Probleme umgangen.

Im folgenden betrachten wir, wie diese Technik mit Silverstripe angewendet werden kann, welche Hindernisse dabei auftreten und wie sie überwunden werden können.

Hintergrundinformation: die Silverstripe Klasse Requirements

Externe Dateien werden in Silverstripe mit Hilfe der Requirementsklasse eingebunden; sie kann sowohl im Template als auch im Controller genutzt werden. Die Dokumentation zur Klasse ist unter "http://api.silverstripe.org/default/Requirements.html" zu finden.

Verwendung der Klasse Requirements im Template "Home.ss"

<html>
<head>
<% require themedCSS(reset) %>
<% require themedCSS(base) %>
<% require themedCSS(tipTip) %>
</head>
</html>

Verwendung der Klasse Requirements im Controller "Home.php"

class Home_Controller extends ContentController
{
public function init()
{
parent::init();

Requirements::themedCSS(reset);
Requirements::themedCSS(base);
Requirements::themedCSS(tipTip);
}
}

Definieren der Requirements und Zusammenfassung im Controller

Um mehrere Dateien zusammenzufassen, müssen wir mit dem Controller in der Methode "init()" beginnen.

Als erstes definieren wir ein numerisches Array, in dem die einzelnen Dateien inklusive Pfad (ausgehend vom Rootverzeichnis) gespeichert werden:

$currentTheme = SSViewer::current_theme();
$cssArray = array(
'themes/'.$currentTheme.'/css/reset.css',
'themes/'.$currentTheme.'/css/base.css',
'themes/'.$currentTheme.'/css/tipTip.css'
);

Im nächsten Schritt geben wir der Klasse Requirements alle Dateien bekannt, die wir einbinden wollen:

foreach($cssArray as $css)
{
    Requirements::css($css);
}

Abschließend sagen wir der Klasse, dass diese Dateien kombiniert werden sollen und übergeben ihr den Ablageort und -namen der kombinierten Datei, sowie die zu kombinierenden Einzeldateien und führen den Kombinationsprozess aus:

Requirements::combine_files(
'assets/suture.css',
$cssArray
);
Requirements::process_combined_files();

Die kombinierte Datei heißt also "suture.css" und liegt im Verzeichnis "assets". Warum sie dort abgelegt wird, wird im Abschnitt "Der richtige Ablageort für die zusammengefasste Datei" erklärt.

Auf den ersten Blick mag es umständlich erscheinen, der Methode "combine_files" die zu kombinierenden Dateien in einem Array (hier "$cssArray") übergeben zu müssen, sie kennt zu diesem Zeitpunkt ja schon die Dateien, die eingebunden werden sollen.

Der Vorteil dieser Maßgabe ist, dass man viele Dateien als Requirement heranziehen kann, aber nur eine Auswahl davon zusammenfassen lässt. Wenn man Dateien zusammenfasst, sollte man die nehmen, die auf allen (oder den meisten) Seiten verwendet werden, um den Browsercache effektiv zu nutzen. Wir können uns also ein Szenario vorstellen, bei dem auf der Seite "Home" neben der kombinierten Datei "suture.css" - deren Angaben auch auf allen anderen Seiten benötigt werden - noch ein weiteres Stylesheet herangezogen wird, das Inhalte exklusiv für diese Seite formatiert.

Hier ist der komplette Quelltext für den Controller:

class Home_Controller extends ContentController
{
public function init()
{
parent::init();

$currentTheme = SSViewer::current_theme();
$cssArray = array(
'themes/'.$currentTheme.'/css/reset.css',
'themes/'.$currentTheme.'/css/base.css',
'themes/'.$currentTheme.'/css/tipTip.css'
);

foreach($cssArray as $css)
{
    Requirements::css($css);
}

Requirements::combine_files(
'assets/suture.css',
$cssArray
);

Requirements:process_combined_files();
}
}

Einbinden der kombinierten Datei im Template

Beim Aufruf der Seite wird die Datei "suture.css" im Verzeichnis "assets" erzeugt. Diese wird durch die Requirementsangaben im Controller (siehe vorheriger Abschnitt) automatisch im Template eingebunden.

Der richtige Ablageort für die zusammengefasste Datei

Im Abschnitt "Definieren der Requirements und Zusammenfassung im Controller" haben wir festgelegt, dass die kombinierte Datei im Verzeichnis "assets" abgelegt werden soll statt im CSS-Verzeichnis des Themes.

Der Grund dafür ist, dass das Verzeichnis vom Webserver beschreibbar sein muss. Das Themes-Verzeichnis sollte bei einer sauberen Installation keine Schreibmöglichkeit für den Webserver bieten; Silverstripe sieht für solche Dateien das Verzeichnis "assets" vor, für das es schon bei der Installation Schreibzugriff fordert.

Suturing im Entwicklungsmodus erlauben

Wenn man im Stylesheet Hintergrundbilder mit einem Pfad definiert und die zusammengesetzte Datei im Verzeichnis "assets" ablegen lässt, werden diese entweder im Entwicklungsmodus oder im Livemodus nicht gefunden, da der Pfad in der Regel aus dem Verzeichnis "templates" heraus gesetzt wird. Um das zu verhindern, kann die Klasse "Requirements" angepasst werden, so dass das Suturing auch im Entwicklungsmodus stattfindet.

Dazu wird in der Klasse Requirements aus "sapphire/core/" die Zeile 819

if((Director::isDev() && !SapphireTest::is_running_test()) || !Requirements::get_combined_files_enabled()) {

ersetzt durch

if((!Requirements::get_combined_files_enabled())) {

Performance

Die Klasse Requirements ist so geschickt angelegt, dass die kombinierte Datei nicht bei jedem Seitenaufruf neu erzeugt wird; damit ist der Overhead für das Kombinieren von Dateien sehr gering.

Die Datei wird nur dann neu erzeugt, wenn:

  • noch keine kombinierte Datei existiert.
  • das Änderungsdatum einer der zu kombinierenden Dateien sich geändert hat.
  • beim Seitenaufruf in der URL "?flush=1" angehängt wird.

Hinweise

Folgendes sollte beachtet werden, wenn man Dateien kombiniert:

  • Im Entwicklungsmodus werden Dateien niemals kombiniert.
  • Kombinierte Dateien werden nur neu erstellt, wenn sich das Änderungsdatum einer der zu kombinierenden Dateien geändert hat oder wenn beim Seitenaufruf in der URL "?flush=1" angefügt wird.
  • Wenn CSS-Dateien kombiniert werden, werden "media"-Angaben entfernt und nicht beachtet.
  • Wenn Javascript-Dateien kombiniert werden, werden sie automatisch mit Hilfe der JSMin-Bibliothek minimiert; dieses Verhalten kann geändert werden, wenn man "Requirements::combine_js_with_jsmin = false" setzt.

Links

Dokumentation der Klasse "Requirements" auf api.silverstripe.org:
http://api.silverstripe.org/default/Requirements.html

Allgemeines zur Verwendung von Requirements in der Silverstripe Dokumentation:
http://doc.silverstripe.org/doku.php?id=requirements

Das "Rezept" zum Zusammenfassen von Requirements in der Silverstripe Dokumentation:
http://doc.silverstripe.org/doku.php?id=recipes:combining_files

Artikel zur Suture-Technik auf Websiteoptimiziation.com (englisch):
http://www.websiteoptimization.com/speed/tweak/suture/

 

 

 

 

 


Geben Sie einen Kommentar ab

Kommentare

Bisher hat niemand diese Seite kommentiert.

RSS Feed für die Kommentare auf dieser Seite | RSS feed für alle Kommentare