[phpBB Debug] PHP Warning: in file [ROOT]/ext/tas2580/seourls/event/listener.php on line 213: Undefined array key "FORUM_NAME"
CSS/JS "onDemand" - REDAXO Forum
Hallo,

Wir haben in letzter Zeit festgestellt, dass die Kommunikation via Slack viel schneller und zielführender ist als ein Beitrag im Forum. Aufgrund der neuen und besseren Möglichkeiten der Kommunikation haben wir uns entschlossen das Forum nur noch als Archiv zur Verfügung zu stellen. Somit bleibt es weiterhin möglich hier nach Lösungen zu suchen. Neue Beiträge können nicht mehr erstellt werden.

Wir empfehlen, für deine Fragen/Probleme Slack zu nutzen. Dort sind viele kompetente Benutzer aktiv und beantworten jegliche Fragen, gerne auch von REDAXO-Anfängern! Slack wird von uns sehr intensiv und meistens "rund um die Uhr" benutzt :-)
Selbst einladen kannst Du dich hier: https://redaxo.org/slack/
BurnedToast
Beiträge: 10
Registriert: 8. Sep 2010, 14:40

CSS/JS "onDemand"

8. Sep 2010, 14:55

Hallo,

erstmal ein Lob an die Entwickler von Redaxo und den Addons/Modulen. Ich verwende Redaxo nun schon seit vielen Jahren und bin sehr zufrieden!

Als ich letztens meine Webseite optimieren wollte habe ich mich geärgert, dass es keine elegante Methode gibt (mir ist zumindest keine bekannt) die CSS/JS-Dateien dynamisch (onDemand) in die Templates einzubinden.

Ich habe ein Modul "Galerie", welches die Javascript-Librarys jQuery und Slimbox, sowie eine galery.css und eine slimbox.css benötigt.
Diese habe ich fest im head des Templates verlinkt -> Folge: Auch auf Seiten auf denen ich keine Galerie anzeige werden diese dateien geladen.

Kurz gesagt:
Spezielle Module benötigen spezielle JS/CSS-Dateien und ich will diese nur laden, wenn das entsprechende Modul im Artikel eingebunden ist.

Also habe ich mir eine kleine Lösung für das Problem ausgedacht:

Ich habe mir ein Template mit dem folgenden Code angelegt: (das Angelegte Template hat die ID 10 und das galerie-Modul die ID 13)

Code: Alles auswählen

<?php
$article = OOArticle::getArticleById(REX_ARTICLE_ID);
$REX['USED_MODULES'] = array();

for ($slice = OOArticleSlice::getFirstSliceForArticle(REX_ARTICLE_ID); $slice != null; $slice = $slice->getNextSlice())  {
	$REX['USED_MODULES'][$slice->getValue('modultyp_id')] = true;
}
?>
Dies habe ich in meinem Haupt-Template ganz an erster Stelle eingebunden. Habe dann für spezielle CSS-Definitionen eine Abfrage eingebaut.

Code: Alles auswählen

REX_TEMPLATE[10]
...
<head>
...
<?php if($REX['USED_MODULES'][13] == true) {?>
	<link href="<?php echo $REX['HTDOCS_PATH'] ?>files/gallery.css" rel="stylesheet" type="text/css" />
	<link href="<?php echo $REX['HTDOCS_PATH'] ?>files/slimbox/slimbox2.css" rel="stylesheet" type="text/css" />
	<script type="text/javascript" src="files/addons/jquery_ui/jquery-1.4.2.min.js"></script>
	<script type="text/javascript" src="files/slimbox/slimbox2.js"></script><?php } ?>
...
</head>
...
Es fnktioniert, aber leider ist die Lösung nicht sonderlich komfortabel und bläht das Template ein klein wenig auf. Aber der Effekt ist es Wert ... Ladezeiten werden besser und es wird kein unnötiger Traffic verursacht!

Gibt es da eventuell schon elegantere Lösungen?

Thomas.Skerbis
Beiträge: 1371
Registriert: 4. Aug 2006, 14:06
Wohnort: Rheinberg
Kontaktdaten: Website Twitter

8. Sep 2010, 15:46

Du kannst es so lösen ..(über einen Outputfilter)
Habe ich mal irgendwo hier im Forum gefunden..

Code: Alles auswählen

$meintext = "\n".'<!-- hiermeintext -->'."\n"; 
$suchtext = 'hiermeinsuchtext'; 

rex_register_extension('OUTPUT_FILTER', create_function('$params', 'if (strpos($params[\'subject\'], \''.$suchtext.'\')===false) return str_replace(\'</head>\',\''.$meintext.'</head>\',$params[\'subject\']);'));

BurnedToast
Beiträge: 10
Registriert: 8. Sep 2010, 14:40

8. Sep 2010, 16:28

Danke für deine Antwort :D

aber so ganz verstehe ich das noch nicht ... kannst du deinen Code bitte nochmal genauer erklären? Ich verstehe noch nicht ganz wie ich den OUTPUT_FILTER für meinen Zweck verwenden könnte!?

Ein str_replace würde ich lieber umgehen, da es wahrscheinlich mehr Performance verbraucht als meine alte Lösung. Aber der Ansatz mit dem OUTPUT_FILTER scheint mir ganz gut ...

Benutzeravatar
xrstf
Beiträge: 65
Registriert: 3. Sep 2009, 15:49

8. Sep 2010, 18:36

Hi,

im OUTPUT_FILTER erhält dein Callback das gerade erzeugte HTML der Seite übergeben. Das ist die allgemein letzte Chance, noch einmal die Seite zu bearbeiten, bevor sie an den Client rausgeschickt wird.

Wenn du willst, kannst du dir ein AddOn basteln, das eine API à la

Code: Alles auswählen

MeinAddOn::addCSSFile($filename)
bereitstellt. Es würde die Dateien dann erst einmal horten und erst im OUTPUT_FILTER die Links in den <head> hängen:

Code: Alles auswählen

class MeinAddOn {
    public static function addCSSFile($file) {
        // ...
    }

    public static function outputFilter($params) {
        $links = self::createHTMLLinksForFiles();
        // $params['subject'] enthält das HTML der Seite
        return str_replace('</head>', $links.'</head>', $params['subject']);
    }
}

// Extension registrieren
rex_register_extension('OUTPUT_FILTER', array('MeinAddOn', 'outputFilter'));
Mit diesem Code könntest du dann jederzeit CSS/JS/Meta/... zum HTML-Kopf hinzufügen und die Links dann erst später schreiben lassen.

Um das str_replace() wirst du dabei allerdings nicht herumkommen. Üblicherweise ist es zu empfehlen, die eigenen Links vor das '</head>' in den HTML-Code zu schreiben.

Grüße,
Christoph
User was banned for this post. [ externes Bild ]

BurnedToast
Beiträge: 10
Registriert: 8. Sep 2010, 14:40

9. Sep 2010, 08:18

Ok super, das hab ich verstanden :D Vielen Dank!

Ich fände ein AddOn, von dieser Art, so oder so sinnvoll und wundere mich, dass es das noch nicht gibt.

Ich könnte mir vorstellen, ein AddOn zu schreiben, welches im Backend einen eigenen Bereich zur Verwaltung und Bearbeitung der CSS- und JS-Daten hat.
Dann würde ich Methoden zur Verfügung stellen wie du es ja schon gezeigt hast um CSS- oder JS-Dateien hinzuzufügen oder zu entfernen, welche dann von beliebiger Stelle aus aufgerufen werden können.
Und ich würde versuchen eine Zuordnung zwischen CSS/JS-Dateien und Modulen zu ermöglichen (ähnlich wie Aktionen Modulen zugeordnet werden) ... so dass definiert werden kann welche Module welche Dateien benötigen und diese dann über das AddOn eingebunden werden.

Wo gibt es denn eine ausführliche Dokumentation zur Erstellung von AddOns? Im Wiki hab ich nix brauchbares gefunden!

Vielen Dank nochmal + Grüße,
Toast

Benutzeravatar
Xong
Beiträge: 2081
Registriert: 5. Jun 2008, 08:30
Wohnort: Halle (Saale)

9. Sep 2010, 09:50

Hi BurnedToast!

Die Lösung über den EP (Extension Point) OUTPUT_FILTER ist nicht die schönste.
Warum es das noch nicht gibt, ist mMn auch klar:
1. Die Performanceeinbußen durch unnötig geladene Dateien sind marginal, da diese nach dem ersten Aufruf gecached werden.
2. Differenzierte Einbindung von JS- und CSS- Dateien im Kopfbereiche einer Seite kann man auch wunderbar in einem eigenen Template kapseln. Ein eigenes Addon halte ich hier für absoluten Overkill.

Aber: So ein Addon könnte u. U. Sinn ergeben in Verbindung mit der Möglichkeit, CSS- und JS- Dateien hinzuzufügen, die dann automatisch durch das Addon im Frontend eingebunden werden.
BurnedToast hat geschrieben:Wo gibt es denn eine ausführliche Dokumentation zur Erstellung von AddOns? Im Wiki hab ich nix brauchbares gefunden!
AddOn-Entwicklung in sieben Folgen
LG,
Xong

[ externes Bild ] Määääääääääääääääääääääääh!

BurnedToast
Beiträge: 10
Registriert: 8. Sep 2010, 14:40

9. Sep 2010, 11:36

... wenn sie benötigt werden, ja.

Mir ist es nur aufgefallen, weil sich mit der Zeit doch einige Module ansammeln, welche spezielle Inhalte haben und spezielle CSS und JS-Dateien benötigen.
Die Performanceeinbußen durch unnötig geladene Dateien sind marginal, da diese nach dem ersten Aufruf gecached werden.
Ich denke, das der Performance-Vorteil sich gerade bei der Suchmaschienenoptimierung auszahlt (die nicht cachen), da die Ladezeiten sich verbessern sollten (wenn das AddOn performant läuft versteht sich).
Auch bei einmaligen Besuchern würde man Traffic spaaren, da diese nicht gleich "alles" laden, somit wird der Server etwas geschont.
Außerdem ist doch der erste Eindruck wichtig ;).
Differenzierte Einbindung von JS- und CSS- Dateien im Kopfbereiche einer Seite kann man auch wunderbar in einem eigenen Template kapseln. Ein eigenes Addon halte ich hier für absoluten Overkill.
Das habe ich getan, bin aber dennoch nicht ganz zufrieden mit der Lösung :), das Addon würde außer einem Caching und einer DB-Abfrage auch nicht mehr machen (so vermute ich zumindest).
Aber: So ein Addon könnte u. U. Sinn ergeben in Verbindung mit der Möglichkeit, CSS- und JS- Dateien hinzuzufügen, die dann automatisch durch das Addon im Frontend eingebunden werden.
Denkst du es kostet so viel mehr Performance wenn man diese Funktionalität um eine Prüfung erweitert ob die spezifische Datei benötigt wird.

Ich stelle mir das im Backend dann so vor, dass man die eingebundenen Dateien auf "global" oder "onDemand" einstellen kann. Globale Dateien werden immer eingebunden ... also alles was grundsätzlich benötigt wird. Und "onDemand" wäre dann das Besprochene.

Es zeichnet sich klar ab, dass das AddOn nur dann einen Performance-Vorteil bringt, wenn es sich um eine große Seite handelt. Kleinere Seiten, bei denen diese Funktionalität nur an einer Stelle benötigt wird werden eine kleine Einbuße erleiden, was sich aber sicherlich mit Caching eingrenzen lässt.
Eine Backend-Funktionalität zur Bearbeitung der CSS/JS-Dateien wäre aber in fast jedem Fall komfortabel, da man dann nicht immer umständlich über den Medienpool oder FTP-Zugang (den man eventuell gar nicht hat) gehen muss.

Ich könnte mir auch noch weitere Vorteile vorstellen, wie die Einbindung von Variablen in die CSS/JS-Dateien. So könnte man z.B. die Grundfarben(oder Hintergrundbilder) seiner Webseite komfortabel über das backend steuern ohne in den Quellcode eingreifen zu müssen (was ja eigentlich die Aufgabe eines CMS seien sollte :D)

Danke für deine Antwort und die Anregungen (und den Link ;))

Grüße Toast

Benutzeravatar
Oliver.Kreischer
Beiträge: 2508
Registriert: 17. Dez 2004, 00:03
Wohnort: Velbert - LA
Kontaktdaten: Website

9. Sep 2010, 11:41

Das Addon von Andi kenne Ihr aber - oder?

http://www.redaxo.de/180-0-addon-detail ... don_id=420

LG
Oliver
> Friends Of REDAXO Gemeinsame REDAXO-Entwicklung!
> REDAXO Agenturen. Eintragen erwünscht!
> Komm in den Slack Channel Es lohnt sich!

BurnedToast
Beiträge: 10
Registriert: 8. Sep 2010, 14:40

9. Sep 2010, 12:00

Ich kenne es noch nicht, wollte es gard mal testen, aber es läuft unter 4.3 leider nicht.
Werd es mir mal ansehen, wenn ich mehr Zeit habe.

Vielleicht kannst du ja mal kurz erläutern in wie fern es in diesem Kontext hilft? Die Details zum AddOn sind ja relativ spaarsam :D

Danke für den Hinweis

Ingo
Beiträge: 782
Registriert: 24. Jun 2010, 00:34

9. Sep 2010, 17:29

Ich schätze das so ein wie Xong, ein Addon für sowas zu programmieren ist über. Wenn du sinnvoll die Ladezeiten für JS / CSS minimieren willst, binde das hier ein: http://code.google.com/p/minify/.

Grüße Ingo

BurnedToast
Beiträge: 10
Registriert: 8. Sep 2010, 14:40

9. Sep 2010, 18:15

Ich arbeite bereits daran und werde es einfach mal austesten!

Ich bin nach wie vor der Meinung, dass Daten, welche nicht benötigt werden auch nicht übertragen werden sollten.

zu Minify: Was noch besser funktioniert als komprimieren ist die Daten gar nicht zu übertragen ;D. Aber ich habe die Gzip-Komprimerung von Redaxo bereits eingeschalten, bin mir aber nicht sicher ob diese auch bei den CSS und JS-Dateien greift.

Wenn nicht wäre sowas wie Minify noch eine coole zusätzliche Sache für mein AddOn ... danke!

BurnedToast
Beiträge: 10
Registriert: 8. Sep 2010, 14:40

10. Sep 2010, 12:35

So hab mal was zusammengebaut, aber damit ich es so bauen konnte wie ich es mir vorgestellt habe musste ich manuell 3 neue Extension-Points erstellen:
MOD_EDIT_FORM (Wenn das Berabeitungsformular für Module aufgebaut wird),
MOD_EDITED (wenn das Bearbeiten-Formular abgeschickt wurde),
MOD_HEADER (Im Kopf der modules - Page)

Die brauchte ich um die Zuordnung ähnlich der Aktionen zu bauen, sicher ich hätte auch eine eigene Oberfläche auf der AddOn-Seite bauen können, aber das gefiel mir nicht.
Und ich denke, dass die Extension-Points so oder so angelegt werden sollten. (wo kann man sowas beantragen)?

Bei Interesse würde ich den Code weiter geben, aber ich werde das AddOn nicht im AddOn-Bereich von Redaxo reinstellen, solange man manuell eingreifen muss um die Extension-Points anzulegen.

Ist bis jetzt nur die grundlegende Funktionalität implementiert, weiterführende Dinge wie Minify oder das Caching habe ich noch nicht erledigt.

Benutzeravatar
Jan.Kristinus
Admin
Beiträge: 2166
Registriert: 24. Aug 2004, 22:11
Wohnort: Frankfurt
Kontaktdaten: ICQ Website

10. Sep 2010, 13:55

Ein anderer Weg..

in der Modulausgabe:
if(!isset($REX['tmp_css']['slimbox']))
$REX['tmp_css']['slimbox'] .= '<link href ... ';

und in den anderen modulen entsprechend..

im template anstatt REX_ARTICLE[] - gaaanz oben

<?php $content = $this->getArticle(); ?>

dann wird quasi der array befuellt und $content kannst du dann normal ausgeben, da ist der Artikel dann drin .

im head: <?php foreach($REX['tmp_css'] as $v){ echo $v; ); ?>

alles etwas untechnisch ausgedrückt, aber ist sehr einfach so, frisst keine extra performance, und ist einigermaßen überschaubar. aber die anderen wege machen auch sinn..

lg

jn

ps.: ich finde lösungen als addon immer am nettesten..
Yakamara Media GmbH & Co. KG | Kaiserstrasse 69 | 60329 Frankfurt
Tel.: 069-900.20.60.30
http://www.yakamara.de/

morfer
Beiträge: 105
Registriert: 24. Mär 2009, 01:58

1. Nov 2010, 23:28

Ich binde Kategorie spezifische JS/CSS Dateien wie folgt ein:

1. Ich erstelle eine Metainformation für Kategorien z.B. mit den Spaltennamen: "cat_codepaste".

2. Ich kann dann unter Struktur auf der gewünschten Kategorie via "Ändern" -> Metainformation bearbeiten den Quellcode bzw. die Links zu den JS/CSS Dateien einfügen.

Im Template dann folgendes über dem </head> noch einfügen:

Code: Alles auswählen

<?php
if($this->getValue("cat_codepaste") != "") 
{
$code = $this->getValue("cat_codepaste");
echo $code;
}
?>
</head>
So kann ich für jede Kategorie zusätzliche JS/CSS Dateien oder auch Quellcode einfügen, ohne ein extra Template benutzen zu müssen.

Kann man auch für jeden Artikel so machen...

Für meine Bedürfnisse völlig ausreichend.

LG Daniel W.

BurnedToast
Beiträge: 10
Registriert: 8. Sep 2010, 14:40

4. Nov 2010, 15:49

Auch ein Weg ... aber in meinem fall wollt ichs ebend Modulspezifisch definieren da ja vor allem Module oft mit eigenem CSS ausgeliefert werden.

Danke

Benutzeravatar
jdlx
Beiträge: 2615
Registriert: 29. Sep 2005, 10:50
Wohnort: Hamburg
Kontaktdaten: Website

4. Nov 2010, 16:02

BurnedToast hat geschrieben:Aber ich habe die Gzip-Komprimerung von Redaxo bereits eingeschalten, bin mir aber nicht sicher ob diese auch bei den CSS und JS-Dateien greift.
Nein, tut sie nicht.. das muß man sich dazustricken. Hab da noch keinen simpel funktionierenden Königsweg gefunden.. es gibt zwar viele Lösungen das automatisiert zu machen, nur von denen die ich ausprobiert hatte, wollte keine richtig laufen. Ich machs grad bei mir so, daß ich gz kompimierte Versionen der CSS/JS files _physisch_ rumliegen hab, und in der .htaccess das so rewrite:

Code: Alles auswählen

AddEncoding gzip .gz
<FilesMatch ".js.gz$">
  AddType "text/javascript" .gz
</FilesMatch>
<FilesMatch ".css.gz$">
  AddType "text/css" .gz
</FilesMatch>
RewriteCond %{HTTP:Accept-encoding} gzip
RewriteCond %{REQUEST_FILENAME} .(js|css)$
RewriteCond %{REQUEST_FILENAME}.gz -f
RewriteRule ^(.*)$ $1.gz [QSA,L]
aber wie gesagt: komfortabel ist das nicht.. wer was gutes hat: her damit! ;)

lg,
j.
vg, Jan

Benutzeravatar
jdlx
Beiträge: 2615
Registriert: 29. Sep 2005, 10:50
Wohnort: Hamburg
Kontaktdaten: Website

4. Nov 2010, 16:10

Jan.Kristinus hat geschrieben:Ein anderer Weg..
Smarte Sache das.. ;)

Allerdings ist der Komfort und die Betriebssicherheit dynamisch über OUTPUT_FILTER zu gehn halt unerreicht.. Performance Bedenken hin oder her (zumindest bei kleinen seiten sag ich mal.. )

lg,
Jan
vg, Jan

Zurück zu „Allgemeines [R4]“