Michael_K: Problem mit module export

Kann mir einer erklären, warum ich hierfür eine Fehlermeldung bzgl. export default bekomme?

"use strict"

(function(MTO){

// private function
function resolver(){
}
  //public function 
MTO.transform = function(){

 }
}(window.MTO = window.MTO || new Object()))

export default MTO;
  1. Tach!

    Kann mir einer erklären, warum ich hierfür eine Fehlermeldung bzgl. export default bekomme?

    Wenn du Module verwendest, brauchst du keine IIFE mehr, weil Module bereits kapseln. Die Fehlermeldung kommt, weil MTO im Scope innerhalb der IIFE sitzt und außerhalb nicht sichtbar ist, und dann auch nicht exportiert werden kann.

    dedlfix.

    1. Tach!

      Wenn du Module verwendest, brauchst du keine IIFE mehr, weil Module bereits kapseln. Die Fehlermeldung kommt, weil MTO im Scope innerhalb der IIFE sitzt und außerhalb nicht sichtbar ist, und dann auch nicht exportiert werden kann.

      Hmm, der erste Satz bleibt gültig. Den zweiten muss ich revidieren, weil ich nicht genau hingeschaut hatte, was du da machst. Bei mir kommt jedenfalls keine Fehlermeldung in meinem Versuchsaufbau. In test.js steckt dein Code.

      <script type="module" src="test.js"></script>
      <script type="module">
        import x from "./test.js";
        console.log(x);
      </script>
      

      Du hängst das MTO ja an das window-Objekt, also in den globalen Namensraum. Damit erübrigt sich im Prinzip der Sinn eines Moduls.

      dedlfix.

      1. Hallo dedflix,

        vielen Dank für die Antwort. Der Sinn dieser "Übung" ist es, die Bibliothek sowohl normal als script in einen Browser oder in einen Web Worker einzubinden, wenn diese Bibliothek nicht als Modul genutzt wird. Gleichzeitig aber nun die Möglichkeit schaffen, diese Bibliothek auch als Modul nutzen zu können.

        Gruss Michael

        1. Tach!

          Der Sinn dieser "Übung" ist es, die Bibliothek sowohl normal als script in einen Browser oder in einen Web Worker einzubinden, wenn diese Bibliothek nicht als Modul genutzt wird. Gleichzeitig aber nun die Möglichkeit schaffen, diese Bibliothek auch als Modul nutzen zu können.

          Das geht nicht in einer Datei. Wenn import oder export verwendet werden, muss das in einem Modul geschehen. Und das war dann wohl auch der Fehler. Die konkrete Meldung zu nennen, ist immer hilfreicher also nur zu sagen, dass einer auftritt.

          Dein Versuch ist wohl zum Scheitern verurteilt. Für ein Modul müssen die zu exportierenden Dingen innerhalb des Moduls global sein. Um sie abseits von Modulen nicht global zu haben, müssen sie in einem Scope stehen. Das sind widersprüchliche Anforderungen.

          Um an privaten Code innerhalb einer IIFE zu kommen, braucht es außerhalb davon eine Referenz. Wenn sie aber schon draußen ist, was bringt dann noch ein Modul außer unnötigem export/import-Handling?

          dedlfix.

  2. Hallo Michael_K,

    ich kriege eine Fehlermeldung, dass "use strict" keine Funktion sei. Hinter "use strict" gehört ein Semikolon, allerdings gehört "use strict"; in ein Modul genauso wenig hinein wie ein IIFE Konstrukt.

    Module sind

    • keine normalen Scripte
    • isoliert, alles was nicht exportiert wird ist lokal im Modul
    • grundsätzlich im strict mode
    • grundsätzlich deferred, d.h. sie werden asynchron geladen und ausgeführt, wenn das DOM fertig ist. Aber noch bevor das DOMContentLoaded-Event ausgelöst wird.
    • werden nur einmal geladen, auch wenn sie drölf mal importiert werden. Deine Erstinitialisierungslogik ist unnötig. Es gibt das MTO Objekt nur einmal.

    Und wie dedlfix schon sagte - die Zuweisung an window.MTO ist kontraproduktiv. Du willst dein MTO Objekt per Export bereitstellen, so dass der Nutzer es importiert.

    Also:

    modul.js

    function resolver() {
      // resolve something
    }
    
    const MTO = {
       transform: function() {
          // transform something
       },
       mutate() {
          // mutate something
       }
    };
    
    export default MTO;
    

    Ich verwende bei mutate die neuere Schreibweise für Objektmethoden. Das ist kürzer als die alte Schreibweise, die ich zum Vergleich bei transform verwendet habe.

    Die Variable MTO brauchst Du genau genommen gar nicht. Du exportierst sie als Default, das ginge auch so:

    export default {
       transform() { ... },
       mutate() { ... }
    };
    

    Und das kannst Du dann ganz normal importieren, so oft wie Du willst.

    <script type="module">
    import WTO from "./mto.js";
    import MTO from "./mto.js";
    
    WTO.transform("world");
    MTO.mutate("genes");
    
    WTO.magic = 13;           // setze neues Property auf WTO
    console.log(MTO.magic);   // lese Property von MTO, gibt trotzdem 13 aus 
    </script>
    

    Die Zuweisung der 13 an WTO.magic zeigt, dass ein mehrfacher Import das Modul nicht mehrfach erzeugt. WTO und MTO referenzieren das gleiche Objekt.

    Rolf

    --
    sumpsi - posui - obstruxi
    1. Hallo Rolf,

      viele Dank für die Info. Das sind hilfreiche Informationen. Vielleicht hätte ich noch etwas mehr Kontext zu meiner Problemstellung geben können.

      Wir haben hier mehrere js Bilbliotheken im Einsatz, die sehr gut funktionieren. Das Problem ist nur, dass diese in verschiedenen Szenrien eingesetzt werden. Einmal direkt im Browser, zum anderen aber auch via importScript in den web workern. Diese bekommen ja nun auch modul import Unterstützung. Grundsätzlich soll langsam alles auf import modul umgestellt werden, aber als "Zwischenlösung" hätte ich gedacht, dass man diese Bibliotheken eben auch via export default nutzbar machen kann.

      Der Aufbau der Bibliotheken war damals so gewählt, um eine Form von Namespacing zu erreichen und auch zwischen public und private function zu unterscheiden. Lettendlich geht es also um eine Lösung, wie die bestehenden Bibliotheken weiter genutzt werden können, gleichzeit aber auch die Nutzung dieser als module zu ermöglichen.

      Gruss, Michael

      1. Hallo Michael_K,

        wie dedlfix schon sagte - ECMAScript-Module und Module auf IIFE-Basis sind inkompatibel und brauchen 2 verschiedene Dateien.

        Man kann das über seinen Entwickler-Toolstack lösen, wenn man ein Transformationsscript schreibt, das an Hand von ein paar Steueranweisungen aus einem gemeinsamen Basis-Sourcecode ein ECMAScript-Modul und ein UMD-Modul erstellt. Letzeres kann man dann bspw. mit requireJs einbinden.

        Ob es solche Transformatoren fertig gibt, oder ob bspw. TypeScript so etwas leisten kann, das weiß ich nicht.

        Rolf

        --
        sumpsi - posui - obstruxi