Verwendung und Unterschied von Js-Modulverpackungsexporten erfordern Import

Verwendung und Unterschied von Js-Modulverpackungsexporten erfordern Import

1. Commonjs-Exporte und erforderliche Nutzung

Commonejs legt fest, dass jede Datei ein Modul ist. Der größte Unterschied zwischen der direkten Einfügen einer JavaScript-Datei in die Seite über das Skript-Tag und der Kapselung in ein CommonJS-Modul besteht darin, dass der oberste Bereich des ersteren der globale Bereich ist, der beim Deklarieren von Variablen und Funktionen die globale Umgebung verschmutzt; während der letztere einen Bereich bildet, der zum Modul selbst gehört, und auf alle Variablen und Funktionen nur vom Modul selbst zugegriffen werden kann und sie für die Außenwelt nicht sichtbar sind.

1.1 CommonJS-Exportmodul.exports

Exporte sind die einzige Möglichkeit, wie sich ein Modul der Außenwelt präsentiert. In CommonJS können Sie den Inhalt eines Moduls über module.exports exportieren, beispielsweise:

modul.exporte = {
    Name: "commonJS_exports.js",
    hinzufügen: Funktion(a, b){
        gib a + b zurück;
    }
}

Zur Vereinfachung des Schreibens unterstützt CommonJS auch eine andere vereinfachte Exportmethode: die direkte Verwendung von Exporten. Die Wirkung ist die gleiche wie oben:

exports.name = "commonJS_exports.js";
exports.add = Funktion(a, b){
    gib a + b zurück;
}

Hinweis: Mischen Sie beim Exportieren nicht module.exports mit exports. Hier ist ein falsches Beispiel:

exports.add = Funktion(a, b){
    gib a + b zurück;
}
modul.exporte = {
    Name: "commonJS_exports.js"
}

Der obige Code exportiert zuerst das Add-Attribut über Exporte und weist dann module.exports einem anderen Objekt neu zu. Dadurch geht das Objekt verloren, das ursprünglich das Add-Attribut hatte, und nur der Name wird exportiert. Daher wird empfohlen, dass die Exportmethode in einem Modul entweder module.exports oder exports verwendet und diese nicht miteinander vermischt.

Um die Lesbarkeit zu verbessern, sollten bei der tatsächlichen Verwendung die Anweisungen module.exports und exports am Ende des Moduls platziert werden.

1.2 CommonJS-Import erforderlich

Verwenden Sie „require“, um Module in CommonJS zu importieren. commonJS_exports.js Exportcode:

console.log('...hallo, ich bin commonJS_exports.js....start..')
//1. Die erste Möglichkeit, module.exports = { zu schreiben
    Name: "commonJS_exports.js",
    hinzufügen: Funktion(a, b){
        gib a + b zurück;
    }
}

Code in die Seite PageModule.vue importieren:

//1. Testen Sie CommonJS-Exporte und fordern Sie
var comObj = erfordern('../api/module/commonJS_exports');
console.log('...name: ', comObj.name);
versuchen{
      console.log('8 + 9 = ', comObj.add(8, 9));
}fangen(e){
      konsole.log(e);
}

Wenn dasselbe Modul außerdem mehrmals in eine Seite importiert wird, wird das Modul nur beim ersten Import ausgeführt. Nachfolgende Importe werden nicht ausgeführt, aber die Ergebnisse der letzten Ausführung werden direkt exportiert. Hier ist ein Beispiel:

var comObj = erfordern('../api/module/commonJS_exports');
                // Rufen Sie den Import erneut auf und stellen Sie fest, dass das importierte Modul nicht erneut ausgeführt wird, aber das nach der letzten Ausführung erhaltene Ergebnis wird direkt exportiert require('../api/module/commonJS_exports');

console.log('...name: ', comObj.name);
versuchen{
      console.log('8 + 9 = ', comObj.add(8, 9));
}fangen(e){
      konsole.log(e);
}

Wir können die folgenden Druckergebnisse in der Konsole sehen und das Importmodul wird tatsächlich nur einmal ausgeführt:

… CommonJS-Importe testen …

...Name: commonJS_exports.js

8 + 9 = 17

Im Modulobjekt gibt es eine Eigenschaft, die aufzeichnet, ob das Modul geladen wurde. Der Standardwert ist „false“. Wenn das Modul zum ersten Mal geladen und ausgeführt wird, wird der Wert auf „true“ gesetzt. Wenn es später erneut geladen wird und „module.loaded“ als „true“ überprüft wird, wird der Modulcode nicht erneut ausgeführt.
Die Funktion require kann Ausdrücke empfangen. Mit dieser Funktion können wir den Modulladepfad dynamisch angeben.

const moduleNames = ['foo.js', 'bar.js'];
moduleNames.fürJeden(name=>{
   erfordern('./' + Name);
})

2. Verwendung des Exports und Imports von ES6-Modulen

Die Modulfunktion wurde erst mit der Veröffentlichung von ES6 im Juni 2015 hinzugefügt. Das ES6-Modul behandelt jede Datei ebenfalls als Modul. Jedes Modul hat seinen eigenen Umfang. Der einzige Unterschied sind die Import- und Exportanweisungen. Import und Export wurden in der ES6-Version auch als reservierte Schlüsselwörter hinzugefügt (Modul in CommonJS ist kein Schlüsselwort).

2.1 ES6-Modulexport

Verwenden Sie im ES6-Modul den Exportbefehl, um das Modul zu exportieren. Es gibt zwei Exportformen:

Benannter Export

Standardexport

2.1.1 Es gibt zwei verschiedene Möglichkeiten, benannte Exporte zu schreiben:

//Die erste Exportmethode: benannter Export //1.1 Die erste Methode des benannten Exports export const name = 'es6_export.js';
export const add = Funktion(a, b) { return a + b; }

// //1.2 Zweite Möglichkeit, benannte Exporte zu schreiben // const name = 'es6_export.js'
// const add = Funktion(a, b){ return a + b; }
// exportieren { Name, hinzufügen };

Die erste Möglichkeit besteht darin, die Variable in einer Zeile zu deklarieren und zu exportieren; die zweite Möglichkeit besteht darin, die Variable zuerst zu deklarieren und sie dann mit derselben Exportanweisung zu exportieren. Die Wirkung beider Schreibmethoden ist gleich. Wenn Sie benannte Exporte verwenden, können Sie die Variable auch mit dem Schlüsselwort „as“ umbenennen. wie:

Konstantenname = "es6_export.js"
const add = Funktion(a, b){ return a + b; }
export { name, add as getSum }; // Name und getSum beim Importieren

2.1.2 Im Gegensatz zu benannten Exporten kann ein Modul nur einen Standardexport haben. wie:

//Die zweite Exportmethode: default export export default{
    Name: 'es6_export',
    hinzufügen: Funktion(a, b){
        gib a + b zurück;
    }
}

Wir können „export default“ als den Export einer Variable mit dem Namen „default“ in die Außenwelt verstehen. Es besteht also keine Notwendigkeit, die Variable als „benannter Export“ zu deklarieren, sondern Sie können sie direkt exportieren.

//Exportzeichenfolge „export default“: „Dies ist eine Datei es6_export.js“
 //Klasse exportieren
 Standardklasse exportieren {...}
 //Anonyme Funktion exportieren export default function(){ ... }

2.2 ES6-Modul Export-Import

Das ES6-Modul verwendet die Importsyntax zum Importieren von Modulen.

2.2.1 Sehen wir uns an, wie benannte Exportmodule importiert werden

Konstantenname = "es6_export.js"
const add = Funktion(a, b){ return a + b; }
export { Name, Hinzufügen };
// importiere {name, add } von '../api/module/es6_export.js'; //Benannte erste Importmethode für Export // importiere * als esObj von '../api/module/es6_export.js'; //Benannte zweite Alias-Gesamtimportmethode für Export importiere {name, add als getSum } von '../api/module/es6_export.js'; //Benannte dritte Alias-Importmethode für Export // //Benannte erste Importmethode für Export // console.log('name: ', name);
// console.log('12 + 21: ', add(12, 21));

// //Benannter Export, zweite Alias-Importmethode // console.log('name: ', esObj.name);
// console.log('12 + 21: ', esObj.add(12, 21));

                //Benannter Export, dritte Alias-Importmethode console.log('name: ', name);
                console.log('12 + 21: ', getSum(12, 21));

Beim Laden eines Moduls mit benannten Exporten sollte auf den Import ein Paar geschweifter Klammern folgen, um die importierten Variablennamen zu umschließen, und diese Variablen müssen dieselben Namen wie die exportierten Variablen haben. Der Effekt des Importierens von Variablen entspricht dem Deklarieren dieser Variablen (Name und Hinzufügen) im aktuellen Bereich und sie können nicht geändert werden, d. h. alle importierten Variablen sind schreibgeschützt.

Darüber hinaus können wir ähnlich wie bei benannten Exporten die importierten Variablen mit dem Schlüsselwort as umbenennen. Beim Importieren mehrerer Variablen können wir auch die allgemeine Importmethode verwenden. Diese Importmethode import * as <myModule> kann alle importierten Variablen als Attribute zum <myModule>-Objekt hinzufügen und so die Auswirkungen auf den aktuellen Bereich verringern.

2.2.2 Schauen wir uns den Import des Standardexports an

//Die zweite Exportmethode: default export export default{
    Name: 'es6_export.js',
    hinzufügen: Funktion(a, b){
        gib a + b zurück;
    }
}
importiere esObj aus „../api/module/es6_export.js“;

// Importtest des Standardnamens export console.log('name: ', esObj.name);
console.log('12 + 21: ', esObj.add(12, 21));

Beim Standardexport folgt auf import direkt der Variablenname, wobei dieser frei angegeben werden kann (hier beispielsweise esObj), was auf den standardmäßig exportierten Wert in es6_export.js verweist. Grundsätzlich kann man es wie folgt verstehen:

importiere { standardmäßig als esObj } von '../api/module/es6_export';

Hinweis: Der Standardexport von benutzerdefinierten Variablennamen ähnelt dem benannten Export von globalen Aliasnamen, allerdings muss auf die benannten globalen Exportaliasnamen nach dem Import ein * als Alias ​​folgen, während auf den Standardexport nach dem Import direkt der benutzerdefinierte Variablenname folgt.

Schauen wir uns abschließend ein Beispiel an, das die beiden Importmethoden mischt:

importiere react, {Component} von 'react'

React entspricht hier dem Standardexport des Moduls und Component ist eine Variable in seinem benannten Export. Hinweis: React muss vor den geschweiften Klammern geschrieben werden und die Reihenfolge kann nicht umgekehrt werden, da sonst ein Syntaxfehler auftritt.

2.2.3 Zusammengesetztes Schreiben.

Manchmal müssen Sie in einem Projekt ein Modul sofort nach dem Import exportieren, z. B. eine Eingabedatei, die speziell zum Sammeln aller Seiten oder Komponenten verwendet wird. Zu diesem Zeitpunkt können Sie die zusammengesetzte Form verwenden:

exportiere {name, add} aus '../api/module/es6_export.js'

Allerdings unterstützt die obige zusammengesetzte Schreibweise derzeit nur Variablen, die durch „benannten Export“ verfügbar gemacht werden. Für den Standardexport gibt es keine entsprechende zusammengesetzte Form, daher können Sie Import und Export nur getrennt schreiben:

importiere esObj aus '../api/module/es6_export.js'
Standard-esObj exportieren

3. Unterschiede zwischen CommonJS- und ES6-Modulen

Oben haben wir zwei Formen der Moduldefinition vorgestellt, CommonJS und ES6-Modul. In der tatsächlichen Entwicklung mischen wir die beiden oft. Vergleichen wir ihre Eigenschaften:

3.1 Dynamisch und statisch

Der wesentlichste Unterschied zwischen CommonJS und ES6 Module besteht darin, dass ersteres Modulabhängigkeiten „dynamisch“ auflöst, während letzteres sie „statisch“ auflöst. Dabei bedeutet „dynamisch“, dass die Erstellung der Modulabhängigkeiten während der Code-Ausführungsphase erfolgt, während „statisch“ bedeutet, dass die Erstellung der Modulabhängigkeiten während der Code-Kompilierungsphase erfolgt.

Schauen wir uns zunächst ein Beispiel für CommonJS an:

// commonJS_exports.js
module.exports = { Name: 'commonJS_exports' }
//Seitenmodul.vue
const name = require('../api/module/commonJS_exports').name;

Wenn das Modul PageModule.vue das Modul commonJS_exports.js lädt, wird der Code in commonJS_exports.js ausgeführt und sein module.exports-Objekt als Rückgabewert der require-Funktion zurückgegeben. Und der Modulpfad von require kann dynamisch angegeben werden und unterstützt die Übergabe eines Ausdrucks. Wir können sogar if-Anweisungen verwenden, um zu bestimmen, ob ein Modul geladen werden soll. Daher gibt es keine Möglichkeit, explizite Abhängigkeiten zu bestimmen, bevor das CommonJS-Modul ausgeführt wird, und der Import und Export von Modulen erfolgt zur Laufzeit des Codes.
Vergleichen wir für dasselbe Beispiel die Schreibmethode des ES6-Moduls:

//es6_export.js
exportiere const name = "es6_export.js";
//Seitenmodul.vue
importiere { Name } von '../api/module/es6_export.js'

Die Import- und Exportanweisungen des ES6-Moduls sind alle deklarativ. Es wird nicht unterstützt, dass der Importpfad ein Ausdruck ist, und die Import- und Exportanweisungen müssen sich im obersten Bereich des Moduls befinden (sie können beispielsweise nicht in einer if-Anweisung platziert werden).

Daher sagen wir, dass das ES6-Modul eine statische Modulstruktur ist und die Modulabhängigkeiten während der Kompilierungsphase des ES6-Codes analysiert werden können. Es bietet gegenüber CommonJS folgende Vorteile:

  • Erkennung und Beseitigung redundanten Codes. Mithilfe statischer Analysetools können wir feststellen, welche Module nicht aufgerufen wurden. Beispielsweise wird bei der Einführung einer Tool-Bibliothek häufig nur ein Teil ihrer Komponenten oder Schnittstellen im Projekt verwendet, es ist jedoch möglich, ihren gesamten Code zu laden. Nicht aufgerufener Modulcode wird nie ausgeführt und wird zu redundantem Code. Mithilfe einer statischen Analyse können beim Verpacken nicht verwendete Module entfernt werden, um die Größe der verpackten Ressourcen zu reduzieren.
  • Überprüfung des Modulvariablentyps. JavaScript ist eine dynamisch typisierte Sprache und prüft vor der Codeausführung nicht auf Typfehler (wie etwa das Aufrufen einer Funktion für einen Zeichenfolgenwert). Die statische Modulstruktur des ES6-Moduls trägt dazu bei, sicherzustellen, dass die zwischen Modulen übergebenen Werte oder Schnittstellentypen korrekt sind.
  • Compileroptimierungen. In dynamischen Modulsystemen wie CommonJS wird unabhängig von der verwendeten Methode grundsätzlich ein Objekt importiert, während das ES6-Modul den direkten Import von Variablen unterstützt, wodurch die Referenzebene reduziert und das Programm effizienter wird.

3.2 Werte kopieren und dynamisches Mapping

Beim Importieren eines Moduls erhält CommonJS eine Kopie des exportierten Werts. Im ES6-Modul handelt es sich um eine dynamische Zuordnung des Werts, und diese Zuordnung ist schreibgeschützt. Beispiel:

//commonJS_exports.js
Variablenanzahl = 0;
modul.exporte = {
    zählen: zählen,
    hinzufügen: Funktion(a, b){
         Anzahl+=1;
         gib a + b zurück;
    }
}
 //Seitenmodul.vue
 var Anzahl = erforderlich('../api/module/commonJS_exports.js').Anzahl;
 var add = require('../api/module/commonJS_exports.js').add;
 console.log(Anzahl); //0 Hier ist „Anzahl“ eine Kopie des Zählwerts in commonJS_exports.js add(2, 3);
 console.log(Anzahl); //0 Änderungen am Variablenwert in commonJS_exports.js wirken sich hier nicht auf den Kopierwert aus count += 1;
 console.log(count); //1 Der kopierte Wert kann geändert werden

Die Anzahl in PageModule.vue ist eine Kopie des Anzahlwerts in commonJS_exports.js. Wenn also die Funktion aufgerufen wird, wird zwar der Anzahlwert im ursprünglichen calculator.js geändert, dies hat jedoch keine Auswirkungen auf die Kopie, die beim Importieren in PageModule.vue erstellt wird. Änderungen an importierten Werten sind in CommonJS hingegen erlaubt. Wir können die Anzahl ändern und PageModule.vue hinzufügen, um ihnen neue Werte zuzuweisen. Da die Werte kopiert werden, wirken sich diese Vorgänge wiederum nicht auf calculator.js selbst aus.

Lassen Sie uns das obige Beispiel mit dem ES6-Modul neu schreiben:

//es6_export.js
lass count = 0;
const add = Funktion(a, b){
    Anzahl += 1;
    gib a + b zurück;
}
export { zählen, hinzufügen }
importiere {Name, Add, Anzahl} aus '../api/module/es6_export';

console.log(Anzahl); //0, Zuordnung des Zählwerts in es6_export.js add(2, 3);
console.log(Anzahl); //1 spiegelt die Änderung des Zählwerts in es6_export.js in Echtzeit wider // Anzahl += 1; //Kann nicht geändert werden, es wird „ReferenceError: Anzahl ist nicht definiert“ ausgegeben.

Das obige Beispiel zeigt, dass die im ES6-Modul importierten Variablen tatsächlich dynamische Zuordnungen der ursprünglichen Werte sind. Die Anzahl in PageModule.vue ist eine Echtzeit-Reflexion des Zählwerts in calculator.js. Wenn wir den Zählwert in calculator.js durch Aufrufen der Add-Funktion ändern, ändert sich auch der Zählwert in PageModule.vue entsprechend.

Wir können die vom ES6-Modul importierten Variablen nicht ändern. Diese Zuordnungsbeziehung kann als Spiegel verstanden werden. Wir können die Originalobjekte in Echtzeit vom Spiegel aus beobachten, aber wir können das Bild im Spiegel nicht manipulieren.

3.3 Zirkuläre Abhängigkeiten

Eine zirkuläre Abhängigkeit liegt vor, wenn Modul A von Modul B und Modul B von Modul A abhängt. Generell sollten zirkuläre Abhängigkeiten in der Entwicklung möglichst vermieden werden, da aus Sicht des Softwaredesigns Einwegabhängigkeiten klarer sind, während zirkuläre Abhängigkeiten eine gewisse Komplexität mit sich bringen. Bei der tatsächlichen Entwicklung treten zirkuläre Abhängigkeiten manchmal auf, ohne dass wir es bemerken. Denn wenn die Komplexität des Projekts ein ausreichendes Ausmaß erreicht, ist die Wahrscheinlichkeit groß, dass versteckte zirkuläre Abhängigkeiten auftreten.

Vereinfacht ausgedrückt lässt sich leicht erkennen, ob zwischen den Modulen A und B eine direkte zirkuläre Abhängigkeit besteht. Die tatsächliche Situation ist jedoch häufig, dass A von B abhängt, B von C abhängt, C von D abhängt und schließlich, nachdem man sich im Kreis gedreht hat, D wieder von A abhängt. Wenn zu viele Zwischenmodule vorhanden sind, ist es schwierig festzustellen, dass zwischen A und B eine implizite zirkuläre Abhängigkeit besteht.

Daher ist der Umgang mit zirkulären Abhängigkeiten ein Problem, mit dem sich Entwickler auseinandersetzen müssen.

3.3.1 Sehen wir uns zunächst ein Beispiel für ein zirkuläres Abhängigkeitsproblem in CommonJS an:

//bar.js
const foo = erfordern('./foo.js');
console.log('Wert von foo: ', foo);
module.exports = „Dies ist bar.js“;
//foo.js
const bar = erfordern('./bar.js');
console.log('Wert von Balken: ', Balken);
module.exports = „Dies ist foo.js“;
//Seitenmodul.vue

erfordern('../api/module/foo.js');
 /*
    Druckergebnisse:
    Wert von foo: {}
    Wert von bar: Dies ist bar.js
* */

Warum ist der Wert von foo ein leeres Objekt? Lassen Sie uns die tatsächliche Ausführungssequenz des Codes von Anfang an überprüfen:

1. PageModule.vue importiert foo.js und beginnt mit der Ausführung des Codes in foo.js.

2. Die erste Anweisung von foo.js importiert bar.js. Zu diesem Zeitpunkt wird foo.js nicht weiter nach unten ausgeführt, sondern tritt in das Innere von bar.js ein.

3. foo.js wird in bar.js benötigt, wodurch eine zirkuläre Abhängigkeit entsteht. Es ist zu beachten, dass das Ausführungsrecht hier nicht an foo.js zurückgegeben wird, sondern dessen Exportwert, also module.exports, direkt übernommen wird. Da foo.js jedoch noch nicht vollständig ausgeführt wurde, ist der exportierte Wert zu diesem Zeitpunkt das standardmäßig leere Objekt. Wenn bar.js die Druckanweisung ausführt, sehen wir daher, dass der Wert von foo in der Konsole ein leeres Objekt ist.

4. Nachdem bar.js ausgeführt wurde, wird das Ausführungsrecht an foo.js zurückgegeben.

5. foo.js wird weiterhin ab der require-Anweisung ausgeführt, druckt den Wert von bar in der Konsole aus (dieser Wert ist korrekt) und der gesamte Prozess wird beendet

Aus dem Obigen können wir ersehen, dass, obwohl alle zyklisch abhängigen Module ausgeführt werden, die von den Modulen importierten Werte nicht unseren Wünschen entsprechen. Betrachten wir es aus der Perspektive der Webpack-Implementierung. Nach dem Verpacken des obigen Beispiels ist es sehr wichtig, den folgenden Code im Bundle zu haben:

//Die require-Funktion
Funktion __webpack_require__(Modul-ID){
   if (installierteModule[Modul-ID]) {
        returniere installierteModule[Modul-ID].Exports;
   }
   //Erstelle ein neues Modul (und lege es in den Cache)
   var module = installierteModule[moduleId] = {
        i: Modul-ID,
        l: falsch,
        Exporte: {}
   }
    //...
}

Wenn PageModule.vue auf foo.js verweist, ist dies gleichbedeutend mit der Ausführung der Funktion __webpack_require__, der Initialisierung eines Modulobjekts und seinem Einfügen in „installierteModule“. Wenn bar.js erneut auf foo.js verweist, wird die Funktion erneut ausgeführt, aber dieses Mal wird der Wert direkt aus installedModules übernommen. Zu diesem Zeitpunkt ist sein module.exports ein leeres Objekt. Dies erklärt das Phänomen, das oben in Schritt 3 auftritt.

3.3.2 Als nächstes schreiben wir das obige Problembeispiel mithilfe des ES6-Moduls neu:

//bar_es6.js
importiere foo aus „./foo_es6.js“;
console.log('Wert von foo: ', foo);
export default „Dies ist bar_es6.js“;
//foo_es6.js
Balken aus „./bar_es6.js“ importieren;
console.log('Wert von Balken: ', Balken);
export default „Dies ist foo_es6.js“;
//Seitenmodul.vue
importiere foo_es6 aus „../api/module/foo_es6.js“;

/* Ergebnisse drucken:
    Wert von foo: undefiniert
    Wert von bar: Dies ist bar_es6.js
* */

Leider kann bar_es6.js auch nicht den korrekten Exportwert von foo_es6.js abrufen. Der einzige Unterschied besteht darin, dass im Gegensatz zu CommonJS, das standardmäßig ein leeres Objekt exportiert, der hier abgerufene Wert undefiniert ist. Wie oben erwähnt, erhält CommonJS beim Importieren eines Moduls eine Kopie des Wertes, während ES6 Module eine dynamische Zuordnung ist

3.3.3 Nutzen wir die Funktionen des ES6-Moduls, um zirkuläre Abhängigkeiten zu unterstützen (korrektes Beispiel):

//bar_es6_2.js
importiere foo aus „./foo_es6_2.js“;
let aufgerufen = false;
Funktionsleiste (Aufrufer) {
    wenn (!aufgerufen){
        aufgerufen = wahr;
        console.log(invoker + ' ruft bar_es6_2.js auf');
        foo('bar_es6_2.js');
    }
}
Standardleiste exportieren;
//foo_es6_2.js
Balken aus „./bar_es6_2.js“ importieren
Funktion foo(Aufrufer){
    console.log(invoker + ' ruft foo_es6_2.js auf');
    bar('foo_es6_2.js');
}
Standard-Foo exportieren;
importiere foo_es6_2 aus '../api/module/foo_es6_2.js'

foo_es6_2('Seitenmodul.vue');
/* Ergebnisse drucken:
    PageModule.vue ruft foo_es6_2.js auf.
    foo_es6_2.js ruft bar_es6_2.js auf.
    bar_es6_2.js ruft foo_es6_2.js auf.
* */

Es ist ersichtlich, dass die zirkulär abhängigen Module foo_es6_2.js und bar_es6_2.js beide die richtigen Exportwerte erhalten. Lassen Sie uns den Ausführungsprozess des Codes analysieren:

1. PageModule.vue importiert foo_es6_2.js als Einstiegspunkt und beginnt mit der Ausführung des Codes in foo_es6_2.js.

2. Importieren Sie bar_es6_2.js aus foo_es6_2.js, und das Ausführungsrecht wird an bar_es6_2.js vergeben.

3. Führen Sie es bis zum Ende in bar_es6_2.js aus, um die Definition der Balkenfunktion abzuschließen. Beachten Sie, dass zu diesem Zeitpunkt der Wert von foo noch undefiniert ist, da foo_es6_2.js noch nicht ausgeführt wurde.

4. Die Ausführung kehrt zu foo_es6_2.js zurück und wird fortgesetzt, bis sie endet, wodurch die Definition der foo-Funktion abgeschlossen wird. Aufgrund der dynamischen Zuordnungsfunktion des ES6-Moduls hat sich der Wert von foo in bar_es6_2.js von undefiniert in die von uns definierte Funktion geändert. Dies ist der wesentliche Unterschied zu CommonJS beim Lösen zirkulärer Abhängigkeiten. Was in CommonJS importiert wird, wird kopiert und ändert sich nicht mit der Änderung des ursprünglichen Werts im Modul.

5. Die Ausführung kehrt zu PageModule.vue zurück und ruft die Funktion foo auf. Zu diesem Zeitpunkt wird foo-->bar-->foo nacheinander ausgeführt und der korrekte Wert wird in der Konsole gedruckt.

Wie aus den obigen Beispielen ersichtlich ist, ermöglichen die Funktionen des ES6-Moduls eine bessere Unterstützung zirkulärer Abhängigkeiten. Es liegt lediglich in der Verantwortung des Entwicklers, sicherzustellen, dass der richtige Exportwert festgelegt wurde, wenn der importierte Wert verwendet wird.

4. Modulverpackungsprinzip

Wie organisiert Webpack Hunderte oder Tausende von Modulen in einem Projekt ordnungsgemäß und führt sie in der erwarteten Reihenfolge im Browser aus? Im Folgenden werden wir das Prinzip untersuchen.

Lassen Sie uns das vorherige Beispiel verwenden:

//commonJS_exports.js
modul.exporte = {
    hinzufügen: Funktion(a, b){
        gib a + b zurück;
    }
}
//Seitenmodul.vue
const comObj = erfordern('../api/module/commonJS_exports');
const sum = comObj.add(2, 3);
console.log('Summe: ', Summe);

Der obige Code nimmt nach dem Verpacken durch Webpack die folgende Form an (aus Gründen der Lesbarkeit wird hier nur die Antwortstruktur des Codes angezeigt):

//Anonyme Funktion sofort ausführen (function(modules){
        //Modul-Cache var installedModules = {};
        //Require implementieren
        Funktion __webpack_require__(Modul-ID){
            //...
        }
        //Führen Sie das Laden des Eintragsmoduls aus return __webpack_require__(__webpack__require__.s == 0);
 })({
        //Module: Alle gepackten Module in Schlüssel-Wert-Form speichern0: function(module, exports, __webpack_require__){
            //Verpackungseintrag module.exports = __webpack_require__("3qiv");
        },
        "3qiv": Funktion (Modul, Exporte, __webpack_require__) {
            //PageModule.vue-Inhalt},
        jkzz: Funktion (Modul, Exporte) {
            //commonJS_exports.js Inhalt}
})

Dies ist das einfachste Webpack-Paket, aber es zeigt deutlich, wie es Module mit Abhängigkeiten miteinander verbindet. Das obige Paket ist in folgende Teile unterteilt:

  • Die äußerste anonyme Funktion wird sofort ausgeführt. Es wird verwendet, um das gesamte Bündel zu umschließen und einen eigenen Bereich zu bilden.
  • installedModules-Objekt. Jedes Modul wird nur beim ersten Laden ausgeführt, danach werden seine exportierten Werte in diesem Objekt gespeichert. Beim erneuten Laden wird der Wert ohne erneute Ausführung direkt von hier übernommen.
  • __webpack_require__-Funktion. Zur Implementierung des Modulladens kann der Modulimport im Browser durch den Aufruf von __webpack_require__(moduleId) abgeschlossen werden.
  • Module-Objekt. Alle Module, die Abhängigkeiten im Projekt haben, werden hier in Form eines Schlüssel-Werts platziert. Der Schlüssel kann als ID eines Moduls verstanden werden, die aus einer Zahl oder einer sehr kurzen Hash-Zeichenfolge besteht; der Wert ist die von einer anonymen Funktion umschlossene Modulentität und die Parameter der anonymen Funktion verleihen jedem Modul die Möglichkeit zum Exportieren und Importieren.

Schauen wir uns als Nächstes an, wie ein Bundle in einem Browser ausgeführt wird:

1. Die Browser-Ausführungsumgebung wird in der äußersten anonymen Funktion initialisiert, einschließlich der Definition des installedModules-Objekts, der __webpack_require__-Funktion usw., um das Laden und die Ausführung des Moduls vorzubereiten.

2. Laden Sie das Eingabemodul. Jedes Paket hat genau ein Einstiegsmodul. Im obigen Beispiel ist PageModule.vue das Einstiegsmodul und der Browser startet die Ausführung von dort aus.

3. Modulcode ausführen. Wenn module.exports ausgeführt wird, wird der Exportwert des Moduls aufgezeichnet. Wenn in der Mitte die Anforderungsfunktion (genauer gesagt __webpack_require__) angetroffen wird, wird das Ausführungsrecht vorübergehend übergeben und der Hauptteil der Funktion __webpack_require__ wird eingegeben, um die Logik anderer Module zu laden.

4. In __webpack_require__ wird ermittelt, ob das zu ladende Modul in den installierten Modulen vorhanden ist. Wenn es vorhanden ist, rufen Sie den Wert direkt ab, andernfalls gehen Sie zurück zu Schritt 3 und führen Sie den Code des Moduls aus, um den exportierten Wert abzurufen.

5. Alle abhängigen Module wurden ausgeführt und schließlich kehrt das Ausführungsrecht zum Einstiegsmodul zurück. Wenn der Code des Eingabemoduls bis zum Ende ausgeführt wird, bedeutet dies, dass das gesamte Paket fertig ist.

Es ist nicht schwer zu erkennen, dass die Schritte 3 und 4 ein rekursiver Prozess sind. Webpack erstellt für jedes Modul eine Umgebung zum Exportieren und Importieren von Modulen, ändert jedoch im Wesentlichen nicht die Ausführungslogik des Codes. Daher ist die Reihenfolge der Codeausführung genau dieselbe wie die Reihenfolge des Modulladens. Dies ist das Geheimnis der Webpack-Modulverpackung.

Oben finden Sie detaillierte Informationen zur Verwendung und den Unterschieden zwischen Js-Modulverpackungen, die exportiert und importiert werden müssen. Weitere Informationen zur Js-Modulverpackung finden Sie in den anderen verwandten Artikeln auf 123WORDPRESS.COM!

Das könnte Sie auch interessieren:
  • Detaillierte Erläuterung zum Anpassen des Verpackungspfads von CSS, JS und Bildern in vue-cli3.0
  • Release BlueShow v1.0 Bildbrowser (ähnlich wie Lightbox) blueshow.js Paket herunterladen
  • vue.config.js Verpackungsoptimierungskonfiguration
  • Bringen Sie Ihnen Schritt für Schritt bei, wie Sie video.js kompilieren und verpacken
  • nuxt.js fügt Umgebungsvariablen hinzu, um die Vorgänge in der Projektverpackungsumgebung zu unterscheiden
  • vue löst das Problem des Verpackungsfehlers uglifyjs-webpack-plugin
  • Zusammenfassung der Methoden zum Komprimieren des Volumens von Vue.js nach dem Verpacken (Vue.js ist nach dem Verpacken zu groß)
  • Lösen Sie das Problem, dass die Datei vendor.js nach der Vue-Verpackung zu groß ist
  • js realisiert das Verpacken mehrerer Bilder in Zip

<<:  Installation und Daemon-Konfiguration von Redis unter Windows und Linux

>>:  Allgemeine Datumsvergleichs- und Berechnungsfunktionen in MySQL

Artikel empfehlen

JavaScript Canvas Tetris-Spiel

Tetris ist ein sehr klassisches kleines Spiel, un...

So verwenden Sie den Skeleton-Bildschirm im Vue-Projekt

Heutzutage ist die Anwendungsentwicklung grundsät...

So vermeiden Sie die URL-Zeitzonenfalle in MySQL

Vorwort Wenn Sie MySQL 6.0.x oder höher (JAR) ver...

Lösung für „Spezialisierter Schlüssel war zu lang“ in MySQL

Inhaltsverzeichnis Lösung 1 Lösung 2 Beim Erstell...

Detaillierte Erläuterung der 4 gängigen Datenquellen in Spark SQL

Allgemeine Lade-/Schreibmethoden Optionen manuell...

Problem mit der Kompilierung des Nginx RTMP-Moduls in der Arm-Version

Inhaltsverzeichnis 1. Vorbereitung: 2. Quellcode-...

CSS imitiert Fernbedienungstasten

Hinweis: Diese Demo wurde in der Miniprogrammumge...

HTML-Multimediaanwendung: Einfügen von Flash-Animationen und Musik in Webseiten

1. Anwendung von Multimedia in HTML_Flash-Animati...

Vue verwendet el-table, um Spalten und Zeilen dynamisch zusammenzuführen

In diesem Artikelbeispiel wird der spezifische Co...

Sehen Sie sich den Befehl zum Ändern der MySQL-Tabellenstruktur an

Kurzbeschreibung Der Editor hat häufig Probleme m...

Wie melde ich mich per Remote-Zugriff bei der MySql-Datenbank an?

Einführung: Manchmal müssen wir zur Entwicklung e...