TYPO3 6.2: CSS- und JavaScript-Dateien in Extbase-Extensions einbinden

Beim Programmieren von Extbase-Extensions in TYPO3 kommt es oft vor, dass die Extensions nicht nur aus dem reinen PHP-Sourcecode besteht, sondern dass auch noch externe Ressource wie CSS-Dateien oder JavaScripte mit dem gerenderten HTML-Code ausgeliefert werden müssen.
Aber wie bindet man diese Ressourcen, also die JavaScripte und CSS-Dateien, in die Extbase-Extension ein. Wohin gehört der Sourcecode, der das bewerktstelligt? Gibt es eventuell mehrere Möglichkeiten die JavaScript- und CSSDateien einzubinden? Und was sind die Vor- und Nachteile der Methoden?

Wie fast immer gibt es in TYPO3 viele Wege, wie man ein Problem lösen kann. Ich möchte hier ein paar der gängigsten Methoden vorstellen und gleichzeitig die Vor- und Nachteile beschreiben, die diese Methoden aufweisen.

Externe JavaScript und CSS-Dateien im TYPOScript Page-Template einbinden

Die wohl gebräuchlichste Art, eine JavaScript-Datei in TYPO3 einzubinden, so dass sie mit einer Extbase-Extension auf einer TYPO3-Seite an den Browser ausgeliefert wird, ist das Einbinden der JavaScript-Datei im Page-Template. Das kann sowohl im Haupt-Template von TYPO3 als auch in einem speziell dafür angelegten Extension-Template auf einer beliebigen Seite im TYPO3-Backend geschehen. Möglich macht das seit TYPO3 4.5 die Funktion includeJS des PAGE Objekts, die den entsprechenden Link zu der Datei iin den Headerpart des ausgelieferten HTML-Codes einfügt.

Hier ein Beispiel in TYPOScript:

page.includeJS {
  1 = http://code.jquery.com/jquery-latest.min.js
  1.external = 1
  1.forceOnTop = 1
  2 = http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js
  2.external = 1
  3 = fileadmin/js/jquery.cookie.js
  4 = fileadmin/js/meine_js_datei.js
}

der folgendes Stück HTML-Code im Header der ausgelieferten Seite generiert:

<script src="http://code.jquery.com/jquery-latest.min.js" type="text/javascript"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js" type="text/javascript"></script>
<script src="fileadmin/js/jquery.cookie.js?1421843811" type="text/javascript"></script>
<script src="fileadmin/js/meine_js_datei.js?1424942853" type="text/javascript"></script>

Unter „4“ wird hier die Datei „meine_js_datei.js“ aus dem Ordner „fileadmin/js“ eingebunden. TYPO3 testet dabei allerdings vorher, ob diese JavaScript-Datei überhaupt auf dem Server vorhanden ist. Das kann natürlich zu Problemen führen, wenn man JavaScript-Dateien einbinden möchte, die auf einem externen Server liegen. Für diesen Zweck gibt es, wie man bei „1“ und „2“ sehen kann, den Parameter „external“ der TYPO3 mitteilt, dass die Datei nicht auf dem eigenen Server liegt und auch keine Überprüfung stattfinden soll. In dem Codebeispiel werden hier unter „1“ die neueste Version von jQuery direkt von „jquery.com“ eingebunden. Bei „2“ wird von der domain „googleapis.com“ die User-Interface-Bibliothek „jQuery UI“ eingefügt.
Damit die Dateien auch in der richtigen Reihenfolge eingebunden werden und etwa nicht zuerst versucht wird eine jQuery-Erweiterung zu initialisieren bevor jQuery überhaupt geladen wurde, kann man noch den Parameter „forceOnTop“ angeben, der bewirkt, dass die entsprechende Datei zuerst geladen wird.

Ähnlich funktioniert das auch mit dem Einbinden von CSS-Dateien. Schreibt man das folgende Stück Code in ein TYPOScript-Template, vorzugsweise das Haupt-Template, dann wird TYPO3 einen Link in den HTML-Header der ausgelieferten Seite setzen, der die CSS-Datei „meine_css_datei.css“ aus dem Ordner „fileadmin/templates/css“ einbindet.

page.includeCSS {
  1 = fileadmin/templates/css/meine_css_datei.css
}

Auch hier können wieder zusätzliche Parameter wie „external“ oder „forceOnTop“ angegeben werden, die es erlauben CSS-Dateien von anderen Servern einzubinden bzw. TYPO3 dazu veranlassen die Datei als erstes einzubinden.

Möchte man die Dateien lieber im Footer als im Header einbinden, z.B. um zu verhindern, dass die Seite erst angezeigt wird, nachdem alle Dateien aus dem HTML-Header geladen wurden, dann sollte man die Funktion „includeJSFooter“ bzw. „includeCSSFooter“ benutzen. Eine Referenz der Parameter der vier Funktionen findet man bei „http://docs.typo3.org/typo3cms/TyposcriptReference/Setup/Page/Index.html“

Vor- und Nachteile beim Einbinden von Dateien im TYPOScript Page-Template

Die Nachteile:

Die CSS-Dateien und JavaScripte werden, weil sie ja im Page-Template stehen, auch dann eingebunden, wenn sie eventuell gar nicht auf der Seite gebraucht werden. Das heißt es werden auch mehr Dateien bzw. Daten über das Internet geladen als eigentlich für die Darstellung der Seite gebraucht werden. Zusätzlich ist auch (beim erstmaligen Laden) für jede Datei ein zusätzlicher Server-Request notwendig, was die Ladezeit unnötig nach oben treibt.

Die Vorteile:

Da TYPO3 alle benötigten CSS-Dateien und JavaScripte als solche bekannt gemacht wurden, können diese mit Hilfe von systemeigenen Funktionen verkleinert, zusammengefügt und gepackt werden (minified, concatenated and compressed). So ist beim Laden der Seite nur ein Server-Request pro CSS-Datei bzw. JavaScript notwendig und die zu ladenden Dateien sind Dank Compression auch noch sehr klein.

Externe JavaScript und CSS-Dateien im TS-Setup der Extbase-Extension einbinden

Natürlich hat auch Extbase selbst Mechanismen um JavaScript- und CSS-Dateien zusammen mit einer Extension auszuliefern. Wie noch bei den alten PI-Base-Extensions von TYPO3 gibt es auch bei Extbase-Extensions die Möglichkeit eine TYPOScript-Setup Datei zu schreiben, die beim Laden der Extension berücksichtigt wird. Diese TS-Setup Datei findet man gewöhnlich im Ordner

/typo3conf/ext//Configuration/TypoScript/setup.txt

Dort kann man, neben der Grundkonfiguration seiner Extbase-Extension, auch angeben ob und welche Dateien beim Ausliefern der Extension mit auf der Seite eingebunden werden sollen. Möchte man zum Beispiel eine JavaScript-Datei zusammen mit der Extbase-Extension ausliefern, so legt man sich im Ordner „/typo3conf/ext//Resources/Public“ einen Ordner „JS“ für Javascript-Dateien an und erstellt darin seine Datei. In meinem Beispiel ist es die Datei „meine_js_datei.js“. Jetzt muss nur noch am Ende der TYPOScript-Setup Datei die Zeile

page.includeJS.tx_ = EXT:/Resources/Public/JS/meine_js_datei.js

eingetragen werden und schon wird jedesmal wenn auf einer Seite die Extbase-Extension angezeigt wird auch die JavaScript-Datei mit ausgeliefert.

Genau so funktioniert das Ganze auch wieder mit CSS-Dateien. Man erstellt sich im Ordner „/typo3conf/ext//Resources/Public“ einen Ordner „CSS“ und legt seine CSS-Dateien dort hinein. Anschließend trägt man in der TYPOScript-Setup Datei die Zeile zum Einbinden ein:

page.includeCSS.tx_ = EXT:/Resources/Public/CSS/meine_css_datei.css

Vor- und Nachteile beim Einbinden von Dateien im TS-Setup der Extbase-Extension

Die Vorteile:

Die Vorteile sind natürlich offensichtlich, es werden immer nur die für eine Extension relevanten Dateien mit der Seite ausgeliefert. Diese können Dateien können natürlich auch verkleinert und gepackt sein (minified and compressed).

Die Nachteile:

Zwar werdem beim Einbinden von CSS-Dateien und JavaScripten im TS-Setup immer nur die Dateien ausgeliefert, die zu den TYPO3-Extensions gehören, die auch wirklich auf der Seite angezeigt werden, aber das muss nicht heißen, dass die Dateien auch bei jedem Controller benötigt werden. Das heißt eventuell wird auch hier überflüssiger Overhead erzeugt. Als Beispiel könnte man eine einfache Darstellung einer Tabelle nehmen, die die beiden Actions „list“ und „show“ besitzt. Die „show“-Action stellt ein einzelnes Objekt aus der Liste dar, die „list“-Action würde eine Listen-Darstellung bieten, die mit Hilfe eines TableSorter-JavaScripts sortiert und gefiltert werden kann. In diesem Beispiel würde dann auch in der Einzelansicht das JavaScript eingebunden werden, obwohl es nicht benötigt wird.

Externe JavaScript und CSS-Dateien im Controller einer Extbase-Extension einbinden

Die bisher vorgestellten Methoden werden für die meisten Anwendungen reichen, aber gerade bei großen Extbase-Extensions mit vielen Controllern hat man oft das Problem, dass abhängig vom Controller bestimmte JavaScripte geladen werden müssen. Zum Beispiel braucht man ein TableSorter-JavaScript zwar bei der Listen-Darstellung der Daten, also der „list“-Action, aber bei der Einzeldarstellung, der „show“-Action, eines Items müsste das Script eigentlich nicht geladen werden.
Die Idee dabei ist, den Link zu der Datei einfach im TSFE bei den Header-Daten einzutragen.

public function listAction() {
   $items = $this->itemRepository->findAll();
   $this->view->assign('items', items);
   $GLOBALS['TSFE']->additionalHeaderData['tx_'] = '';
}

Hier wieder das entsprechende Code-Stück für das Einbinden von CSS-Dateien.

$GLOBALS['TSFE']->additionalHeaderData['tx_test'] = '';

Dadurch wird die angegebene Zeile im Header-Teil des ausgelieferten TYPO3-Seite eingetragen.

Vor- und Nachteile beim Einbinden von JavaScript und CSS-Dateien im Controller einer Extbase-Extension

Die Vorteile:

Es werden jetzt tatsächlich nur noch die Dateien ausgeliefert, die tatsächlich zum Anzeigen und zur Funktion der TYPO3-Extension gebraucht werden. Das ist natürlich gerade bei Webseiten interessant, die sehr viele Extensions mit sehr vielen Controllern besitzen und bei denen immer nur sehr wenige davon gleichzeitig auf einer Seite angezeigt werden.

Die Nachteile:

Für das Verkleinern und Packen (minify and compress) der Dateien muss man bei dieser Methode leider selbst sorgen. Ein weiterer Nachteil fällt ins Gewicht, wenn sehr viele kleine Extensions gleichzeitig auf einer Seite angezeigt werden. Dort würde dann ja wieder für jede dieser Dateien ein zusätzlicher Server-Request notwendig, der die Ladezeit der Seite nach oben treibt.

Fazit:

Für welche Art seine Dateien einzubinden man sich letztendlich entscheidet, hängt ganz von der Größe und Anzahl der einzubindenden Dateien ab. Meist wird es auch eine Kombination der verschiedenen Möglichkeiten herauslaufen. Es kann durchaus sinnvoll sein die CSS-Dateien, die die generelle Struktur der Seite und das Layout der TYPO3-Inhaltselemente beschreibt, statisch im Seiten-Template und die Action spezifischen Dateien direkt im Code des Controllers der Extbase-Extension einzubauen.