Christian Wansart: Was hat es mit AMD auf sich?

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

akzeptierte Antworten

  1. Tach!

    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.

    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.

    1. 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

  2. @@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 🖖

    --
    “When UX doesn’t consider all users, shouldn’t it be known as ‘Some User Experience’ or... SUX? #a11y” —Billy Gregory
    1. 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

  3. 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

    1. 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

    2. 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

      1. Hm. Wie ist das denn in dem edX Kontext? Verwenden die r.js nicht? Ansonsten müssten sie ja das gleiche Problem haben...

        Rolf

        1. 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

  4. 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?

    1. 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

    2. 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.