Wikipedia:Technik/Skin/JS/ResourceLoader
Der ResourceLoader (RL) ist eine durch MediaWiki entwickelte Software, über die sich dynamisch JS- und CSS-Definitionen in das HTML-Dokument einer Wiki-Seite einbinden lassen.
Die Funktionalität steht mit der Version 1.17 im Februar 2011 zur Verfügung und wird weiter ausgebaut.
Ausschlaggebend für die Entwicklung waren folgende Gesichtspunkte:
- Die Anzahl der verfügbaren unabhängigen Module liegt Anfang 2012 bei über 100 – künftig ist mit einer erheblichen Zunahme zu rechnen. Das ist irgendwann nicht mehr ohne Hilfsmittel zu überschauen und zu pflegen.
- Nicht alle Funktionen werden immer, von jedem Benutzer, für jeden Seiteninhalt, für jede individuelle Konfiguration benötigt. Es ist nicht mehr möglich, wie früher einfach immer zu jeder Seite alle Skripte mitzuliefern.
- Die Ressourcen erwies sich oft als veraltet bei den Lesern und in deren Browser. Der Browser-Cache und vor allem Proxy-Server setzen die mitgelieferten Angaben zum Cache-Management nicht richtig um. Nunmehr wird die Aktualität dadurch sichergestellt, dass eine neue URL generiert wird, wenn sich etwas am Inhalt ändert. Dadurch muss zwangsweise eine neue Version beim Server abgerufen werden.
- Ab Frühjahr/Mitte 2011 begann zunächst Google Chrome, danach Firefox mit dem „asynchronen Laden“ von Ressourcen. Damit funktionieren alte Skripte nicht mehr, die davon ausgehen, dass ein Skript nach dem anderen in einer festen und bekannten Reihenfolge ausgeführt wird.
Anwendungsbereich
Zentrale MediaWiki-Software
Alle Standardsoftware von MediaWiki wird inzwischen mit Methoden des RL eingebunden: /resources/
Projektweite Standardressourcen
Dies sind:
- MediaWiki:Common.js und die zur aktuellen Skin gehörende Seite, etwa MediaWiki:Vector.js
- Analog MediaWiki:Common.css und die zur aktuellen Skin gehörende Seite, etwa MediaWiki:Vector.css
Modulname: site
Projektweite Helferlein
Auf MediaWiki:Gadgets-definition kann angegeben werden, dass mittels RL geladen werden soll; damit werden auch für jede Version spezifische URL generiert und es wird komprimiert.
- Zukünftig soll es die Möglichkeit geben, weltweit verfügbare Module an einer zentralen Stelle vollständig vorzuhalten (Version 2).
Standardressourcen des momentanen Benutzers
Dies sind:
- common.js und die zur aktuellen Skin gehörende Seite, etwa vector.js
- Analog common.css und die zur aktuellen Skin gehörende Seite, etwa vector.css
Modulname: user
Benutzerskripte
Auf eigenständige Ressourcen der Benutzer ist der ResourceLoader 2012 nicht besonders zugeschnitten; er lässt sich aber trotzdem einsetzen: Anwendungsbeispiel.
PHP auf dem Server
Diese Seite beschreibt schwerpunktmäßig den ResourceLoader auf der Browser-Seite in JavaScript; daneben gibt es einen analogen in PHP geschriebenen ResourceLoader auf den Servern; namentlich auf bits.wikimedia.org zur Zusammenstellung.
- Resources.php – Zusammenstellung der Module (möglicherweise bereits zukünftige Version)
- load.php – ResourceLoader
Das Modul
Ein Modul ist die Zusammenfassung folgender Komponenten, die einen inhaltlichen Bezug haben sollten:
- Modul-Name (unentbehrlich)
- JavaScript (praktisch immer)
- CSS (optional)
- Systemnachrichten (optional)
Die Quellen können von einer oder mehreren Seiten stammen oder spontan generiert worden sein.
Mit Vollzugsmeldung für einen Modul-Namen bestätigt die Software, dass eine bestimmte Funktionalität (JS-Funktionen, CSS-Deklarationen) einsatzbereit ist. Es wird keine Aussage darüber getroffen, woher diese Funktionalität stammt und welche von mehreren Varianten vorliegt.
Name
- Jedes Modul wird durch einen Modul-Namen (eigentlich: -Identifikator, -Bezeichner) angesprochen.
- Grundsätzlich ist es egal, wie dieser Name lautet; es könnte auch „Rumpelstilzchen“ heißen, solange es nicht zu Namenskonflikten kommt.
- Es haben sich aber einige Regeln herausgebildet:
- Es werden ASCII-Zeichen (ohne Leerzeichen) verwendet.
- Überwiegend werden Kleinbuchstaben benutzt.
- Gliederung durch Punkte.
- Für individuelle Benutzer hat sich noch kein Schema herausgebildet.
Gebräuchliche Namen sind beispielsweise:
mediawiki.util
- Ein Modul mit verschiedenen Hilfsfunktionen (Quelle)
jquery.colorUtil
- Ein Modul mit Hilfsfunktionen zu Farben (Quelle)
site
- Projektweite Standardressourcen (für das momentane Projekt)
user
- Standardressourcen des momentanen Benutzers
user.options
- Konfiguration des momentanen Benutzers
ext.gadget.Zeitzonenkonverter
Speicherort
Aus dem Modulnamen lässt sich durch Menschen erraten, auf welcher Seite eine Quelle gespeichert sein könnte; aber dies lässt sich nicht durchgängig automatisch generieren. Es besteht der gleiche feine Unterschied wie zwischen URL und URN.
- Das Modul kann on-the-fly generiert worden sein; dann gibt es keine Seite.
- Das gleiche Modul kann in verschiedenen Projekten gespeichert sein; es kann in unterschiedlichen Entwicklungsständen verfügbar sein.
- Von welcher URL das Modul geladen wurde, spielt letzlich keine Rolle. Entscheidend ist, dass die zugesicherte Funktionalität unterstützt wird.
Debug-Modus
Jede Ressource lässt sich in zwei Varianten vom Server laden:
debug=false
(Standardvorgabe)- Alle gleichzeitig benötigten Skripte und CSS-Definitionen werden hintereinander weg in eine URL geschrieben und auch als eine kompakte Ressource vom Server geliefert.
- Weil nur eine URL abgefragt wird, ist der Verkehr zwischen Benutzern und Server geringer.
- Weil gerade im allgemeinen Bereich der Seite immer dieselben Kombinationen von Ressourcen auftreten, kann der Server (und auch Proxy-Server) das Paket für alle Benutzer vorhalten.
- Der Code jedes einzelnen Skriptes und CSS wird komprimiert:
- Alle Kommentare werden gelöscht.
- Alle entbehrlichen Whitespace-Zeichen werden entfernt.
- Es wird eine Zeilenlänge von etwa 1000 Zeichen durch Verkettung einzelner Statements hergestellt; die (korrekte) Syntax von JavaScript und CSS erlaubt das.
- Bei erkannten groben Syntaxfehlern in den Quellen wird die Ressource nicht ausgeliefert, statt dessen eine Fehlermeldung gesendet.
- Die Komprimierung ist allerdings nicht ganz unproblematisch; bei syntaktisch falscher Programmierung kann es zu falschen Konstruktionen kommen, und es werden Syntaxkonstrukte nicht erkannt, die aber auch nicht von jedem Browser richtig interpretiert werden.
- In den Zeilen von 1000 Zeichen Länge ist bei auftretenden Folgefehlern keine unmittelbare Analyse möglich.
- Alle gleichzeitig benötigten Skripte und CSS-Definitionen werden hintereinander weg in eine URL geschrieben und auch als eine kompakte Ressource vom Server geliefert.
debug=true
- Es erfolgt keine Komprimierung.
- Jede Ressource wird einzeln geliefert, so wie sie auch im Quellprogramm definiert ist. Damit sind Zeilennummern identisch.
- Standardmäßig wird ein Hilfsmittel geladen, das die Auswertung in der Fehlerkonsole unterstützen soll.
Browser-Cache
An die URL auf //bits.wikimedia.org
mittels load.php
wird die jeweils jüngste Änderungszeit auf dem Server mit einer Genauigkeit von zehn Sekunden angefügt. Damit hat jedes Paket eine eindeutige URL, die sich von veralteten Versionen im Browser-Cache unterscheidet. Somit bleibt Browsern und Proxy-Servern nichts anderes übrig, als die aktuelle Version herunterzuladen.
Für die Standardressourcen des Projekts und Benutzers sowie Gadgets wird vom Server dieser Zeitschlüssel an die URL angefügt.
Betreffend der weltweit einheitlichen zentralen MediaWiki-Software wird ein Verzeichnis aller erhältlichen Module mit den jeweiligen Zeitschlüsseln in jede HTML-Seite eingeschrieben. Diese Liste hat selbst aber zurzeit (MW 1.18) keinen Versionscode; eine Veränderung eines Zeitschlüssels eines Moduls hätte somit keine neue URL zur Folge. Allerdings gelten die Module der zentralen Software als stabil und werden normalerweise zur Laufzeit einer Version nicht verändert.
mw.loader
Im mw-Objekt steht der ResourceLoader als Komponente .loader
zur Verfügung.
- mw.loader.getState(module)
- Status einer Ressource abfragen.
module
: String mit Modulname.
- Rückgabewert ist eine Zeichenkette, wenn das Modul bislang irgendwie bekannt geworden war.
- "
registered
" – Modulname ist bekannt – definiert in .loader.register(). - "
loading
" – Modul wird zurzeit geladen. - "
loaded
" – Dieses Modul wurde erfolgreich einzeln geladen. - "
ready
" – Dieses Modul und alle seine Abhängigkeiten wurden geladen. - "
error
" – Dieses Modul hat möglicherweise einen Syntaxfehler. - "
missing
" – Zugriff auf die URL dieses Moduls gescheitert. null
– Modulname ist nicht bekannt
- "
- Wenn eine Wiki-Seite geladen wurde, sind die Registrierungsinformationen aller unter //bits.wikimedia.org nutzbaren Module (einschließlich Versionsinfo) definiert; zunächst als
registered
, ggf. auch schon alsready
.
- mw.loader.getVersion(module)
- Versionsinformation einer Ressource abfragen – definiert in .loader.register().
module
: String mit Modulname.
- Rückgabewert ist eine Zeichenkette, wenn das Modul bekannt ist.
- String – ISO8601 YYYYMMDDThhmmssZ, oder "
19700101T000000Z
" wenn nicht vereinbart. null
– Modulname ist nicht bekannt
- String – ISO8601 YYYYMMDDThhmmssZ, oder "
- mw.loader.implement(module, script, style, msgs)
- Deklaration eines neuen Modulnamens, Verbindung mit der zugehörigen Implementierung und Laden.
module
: String mit Modulname. Darf noch nicht registriert gewesen sein.script
: Auszuführende Funktion (Code) oder Array von URL mit JS-Codestyle
: Objekt; entweder aus direkten CSS-Deklarationen oder Liste der URL von CSS-Deklarationen – nichtnull
.msgs
: Objekt; benötigte Systemnachrichten, die den .messages hinzuzufügen sind, als key:value – nichtnull
.
- Wirkung: Die Funktion wird ausgeführt oder die Skript-Quellen werden von den angegebenen URL abgerufen, indem <script src=> in das Dokument eingefügt wird. War das Laden erfolgreich, wird der Status
loaded
gesetzt;missing
odererror
wenn ein Fehler detektiert wurde. Im Erfolgsfall wird nach aufgelaufenen unbefriedigten Abhängigkeiten gesucht; sind keine mehr vorhanden, wirdready
für das Modul ausgewiesen. Schließlich werden eventuelle Funktionen aus der .loader.using()-Warteschlange ausgeführt. - Konzept: Während .loader.register() ein einheitliches Modul weltweit unter einer URL (auf bits.wikimedia.org) zugänglich macht und die offizielle Verteilung der Systemnachrichten über translatewiki nutzt, ermöglicht implement() eine einzelne, örtliche Vereinbarung eines Moduls. Es kann unter verschiedenen URL in verschiedenen Wikiprojekten und in verschieden weit entwickelten Versionen ein Modul bereitgestellt werden. Im Inneren kann bereits so programmiert werden, als ob es sich um ein „offizielles“ Modul handeln würde, also etwa mittels Systemnachrichten.
- mw.loader.load()
-
- .loader.load(URL, MIME)
- Siehe Laden anderer Skripte für JavaScript und CSS, etwa Benutzerskripte.
- .loader.load(modules)
- Laden eines Moduls (oder mehrerer Module) einschließlich aller weiteren Module, von denen diese abhängen.
modules
: String mit Modulname, oder Array mit Modulnamen.- War das Modul bereits geladen gewesen, sollte nichts weiter passieren.
- Soll anschließend eine Funktion ausgeführt werden, wäre .loader.using() zu verwenden. Wenn das Skript selbst eine Art AutoRun-Funktion enthält, kann .loader.load() benutzt werden.
- .loader.load(URL, MIME)
- mw.loader.register(module, version, dependencies, group, source)
- Registrierung eines Moduls zum Abruf über
load.php
(von //bits.wikimedia.org) - Für Benutzerskripte nicht nutzbar.
module
: String mit Modulnamen, oder Array.version
: Versionsnummer; erlaubt Unterscheidung im Browser-Cache.
Erwartet wird die Anzahl der Sekunden seit dem 1. Januar 1970, 00:00:00.dependencies
: Abhängigkeiten; Array→String oder einzelner String oder Function→Array.group
: Übergeordneter Modulname, wennmodule
ein Untermodul ist.source
: aktuelles Wikiprojekt (wgLoadScript; Vorgabe), oder anderes Wiki; Pfad vorload.php
- Erster Parameter Pflicht, Rest optional.
- mw.loader.state(module, state)
- Setze den Status einer Ressource.
- Siehe .loader.getState()
- mw.loader.using(dependencies, ready, error)
- Starte eine Funktion, nachdem ein Modul geladen wurde, oder wenn dies fehlschlug; lade fehlende weitere Module nach.
dependencies
: String oder Array – Name/n der Module, die vor der Ausführung vonready
geladen sein müssen. Schließt automatisch diejenigen Module ein, von denen sie intern abhängen.ready
: Funktion, die ausgeführt wird, nachdem alle Module geladen worden sind.error
: (optional) Funktion, die ausgeführt wird, falls das zusätzliche Laden fehlschlug.
Die restlichen Funktionen sind zurzeit für lokale Projekte und Benutzer kaum einsetzbar.
Benutzer-Skript
Um ein bibliotheksartiges Benutzer-Skript (übergangsweise) für bedarfsweises Laden durch den ResourceLoader auszustatten, ist wie folgt vorzugehen:
- Eindeutigen und langfristig haltbaren Modul-Namen vergeben.
- Am Ende des Skriptes mit
.loader.state(
name, "ready")
das abgeschlossene Laden deklarieren. Falls das Skript zuvor auf eine andere Weise geladen würde, wird ein unnötiger und möglicherweise zu Fehlfunktionen führender mehrfacher Abruf vermieden. - Den Anwendern den Modul-Namen bekanntgeben sowie mögliche URL mit den Quellen.
- Für den weiteren Einsatz siehe Anwendungsbeispiel.
- Komprimierung und Versionsaktualiserung erfolgen dabei jedoch nicht.
Siehe auch
- mw – Projektseite