Was hat es mit AMD auf sich?
Christian Wansart
- javascript
Guten Morgen,
ich arbeite zurzeit an einem Projekt mit edx-platform für das ich ein Modul (ein sogenanntes XBlock schreibe. Nun bindet edX bereits RequireJS ein, was ich auch in meinem Modul benutze. Jedoch packt edX RequireJS aus Kompatibilitätsgründen die Funktionen require
und define
in den Namensbereich RequireJS.
Aus require
wird RequireJS.require
und aus define
wird RequireJS.define
. Nun kann ich das in meinem Code nicht einfach ändern, da dieser auch noch von einem anderen Projekt benutzt wird.
Meine Idee war es, über die von r.js
zusammengestellte Datei einfach define
und require
einfach zu suchen und zu ersetzen, jedoch ersetze ich dann möglicherweise Begriffe wie „undefined“.
Das große Problem ist, dass mein JavaScript-Code verschiedene Bibliotheken braucht wie jQuery, KnockoutJS und KineticJS, welche ebenfalls auf define und define.amd prüfen.
Habt ihr Ideen, wie ich das Problem angehen könnte?
Freundliche Grüße
Christian
Tach!
Jedoch packt edX RequireJS aus Kompatibilitätsgründen die Funktionen
require
unddefine
in den Namensbereich RequireJS. Ausrequire
wirdRequireJS.require
und ausdefine
wirdRequireJS.define
. Nun kann ich das in meinem Code nicht einfach ändern, da dieser auch noch von einem anderen Projekt benutzt wird.
Wenn es keine Konfigurationseinstellung gibt, dem RequireJS zu sagen, dass es die beiden Funktionen im globalen Namensraum anlegen soll, kannst du immer noch im globalen Scope zwei Variablen namens require und define mit einer Referenz auf das RequireJS-Pendant anegen.
dedlfix.
Moin dedflix,
das hatte ich anfangs auch gemacht, jedoch kracht es dann auf der edX-Seite an anderer Stelle.
Ich könnte aber in meine „bundle.js“ das eventuell am Anfang machen und dahinter wieder entfernen. Ich denke, das probiere ich mal aus.
Freundliche Grüße
Christian
@@Christian Wansart
var require = RequireJS.require;
var define = RequireJS.define;
Dann kannst du require()
und define()
aufrufen und sie tun dasselbe wie RequireJS.require()
bzw. RequireJS.define
.
LLAP 🖖
Guten Morgen @Gunnar Bittersmann,
genau deshalb möchte ich in meiner „bundle.js“, in der der gesamte JavaScript-Code meines XBlocks drin ist, define und require durch entsprechende RequireJS.define und RequireJS.require ersetzen.
Was sich nun beim Suchen nach „define“ in der bundle.js ergeben hat ist, dass dort auch im Quellcode von jQuery und anderen Bibliotheken nach define und define.amd gesucht wird und diese ggf. nutzen. Das müsste ich ja auch irgendwie umleiten, was mit einem einfachen Suchen und Ersetzen nicht geht, da ich dann ggf. auch Bezeichner erwische, die wie wie undefined
nur einen Teil ausmachen.
Freundliche Grüße
Christian
Die edX-er werden sicherlich einen Grund gehabt haben, weshalb sie require und define in ein eigenes Objekt gepackt haben. Wenn Du die beiden Funktionen in den globalen Kontext zurücktransportierst, könnte es genau die Probleme geben, zu deren Lösung das RequireJS Kapselobjekt angelegt wurde.
Wäre es für dich eine Alternative, wenn Du in deinem "anderen Projekt" eine globale Variable namens RequireJS anlegst und in deinem Modul so tust, als wärest Du immer im edX Kontext? Also so:
var RequireJS = {
require: require,
define: define
};
Rolf
Das habe ich auch schon überlegt. Dafür müsste ich zwar einige Dateien anpassen, aber das sollte wohl machbar sein.
Interessant ist vielleicht noch folgendes: ich habe ein minimales Projekt gemacht was so funktioniert. Im XBlock habe ich den folgenden Code:
window.require = RequireJS.requirejs;
window.define = RequireJS.require;
window.requirejs = RequireJS.define;
define('index',['jquery'], function($) {
console.log('JUP LÄUFT');
});
requirejs(["index"]);
define("main", function(){});
RequireJS.requirejs = RequireJS.requirejs || window.requirejs;
RequireJS.require = RequireJS.require || window.require;
RequireJS.define = RequireJS.define || window.define;
window.require = undefined;
window.define = undefined;
window.requirejs = undefined;
Ebenfalls kommt es bei dem define('index'... zu einem Fehler:
Uncaught Error: Module name "index" has not been loaded yet for context: _. Use require([]) http://requirejs.org/docs/errors.html#notloaded at makeError (require.js:168) at Object.localRequire [as require] (require.js:1436) at requirejs (require.js:1797) at 1?activate_block_id=block-v1%3ATest%2BTest%2BTest%2Btype%40vertical%2Bblock%407cc7f……:1253
Jetzt muss ich nur noch herausfinden, was ich da machen kann. Ich denke, ich werde aber deinen Vorschlag mal ausprobieren.
Freundliche Grüße
Christian
Moin,
lokal funktioniert es, aber r.js
kann mit RequireJS.define nichts anfangen und fügt die nicht zusammen… Ich könnte r.js eventuell umschreiben, um das ans Laufen zu bringen. 😕
Beste Grüße
Christian
Hm. Wie ist das denn in dem edX Kontext? Verwenden die r.js nicht? Ansonsten müssten sie ja das gleiche Problem haben...
Rolf
Moin,
ne, die verwenden glaube ich intern kein r.js. Deren Code nutzt halt den Namensbereich RequireJS.
ABER ich habe das Problem lösen können. Ich konnte in die build.js, die die Optionen für r.js enthält die Option namespace: "RequireJS"
angeben. Der wandelt meinen Code, den er einliest um und macht aus define entsprechend RequireJS und so.
Nun funktioniert es!
Vielen Dank für deine Hilfe, es hat mich auf die richtige Fährte gebracht.
Freundliche Grüße
Christian
Das große Problem ist, dass mein JavaScript-Code verschiedene Bibliotheken braucht wie jQuery, KnockoutJS und KineticJS, welche ebenfalls auf define und define.amd prüfen.
Habt ihr Ideen, wie ich das Problem angehen könnte?
Ja. Nachsehen, welche der libs durch 10 Zeilen nativen Code oder eben die anderen Libs ersetzt werden können.
##Hinweise:##
KineticJS: KineticJS is a fast, robust, HTML5 Canvas Library that is no longer maintained. :: Muss also ohnehin ausgetauscht werden, für neue Projekte nimmt man sowas nicht mehr.
KnockoutJS: Gab es für den Anwendungsbereich nicht auch jQuery UI?
Guten Morgen Regina,
das Problem habe ich nun gelöst. edX hat RequireJS in einen anderen Namensraum geschoben, weswegen ich meinen Code irgendwie dazu bringen muss, diesen auszuführen. RequireJS selbst mitausliefern funktioniert nicht. Hier hat mir nun r.js
mit der Option namespace
weitergeholfen.
Ja. Nachsehen, welche der libs durch 10 Zeilen nativen Code oder eben die anderen Libs ersetzt werden können.
Grundsätzlich stimme ich dir zu, jedoch setzt die Software massiv auf JavaScript. Wir reden von wahrscheinlich mehr als 10.000 Zeilen JavaScript-Code…
KineticJS: KineticJS is a fast, robust, HTML5 Canvas Library that is no longer maintained. :: Muss also ohnehin ausgetauscht werden, für neue Projekte nimmt man sowas nicht mehr.
Dessen bin ich mir bewusst. Aber: zurzeit läuft dort KineticJS Version 4.7.0. Nicht einmal ein einfaches Austauschen mit Version 4.7.4 funktioniert. Die Überlegung Kinetic komplett rauszuschmeißen kam auch schon, gegen eigenen nativen JavaScript-Code oder gar eine alternative Bibliothek auszutauschen. Jedoch ist das gerade nicht der Auftrag und es gibt genug andere Sachen zu tun, sodass ich das zurzeit einfach nicht machen kann. Die Software ist auch zu aufwendig, um das einfach mal eben rauszunehmen. Leider.
KnockoutJS: Gab es für den Anwendungsbereich nicht auch jQuery UI?
Sicher? Das wird für Observables genutzt. Wenn du mich fragst, in dieser Software eher ohne Notwendigkeit, aber nun ja. Immerhin konnte ich KnockoutJS ohne Probleme auf die aktuelle Version updaten.
Freundliche Grüße
Christian
Tach!
KnockoutJS: Gab es für den Anwendungsbereich nicht auch jQuery UI?
Nein, andere Baustelle. jQuery UI sind Komponenten für das Frontend in Webanwendungen. KnockoutJS ist Datenbindung, ein Bindeglied zwischen Backend und Frontend von Webanwendungen.
dedlfix.