In einem Projekt, an dem ich zusammenarbeite, haben wir zwei Möglichkeiten, welches Modulsystem wir verwenden können:
require
und Exportieren mit module.exports
und exports.foo
.import
importieren und mit ES6 export
exportierenGibt es irgendwelche Leistungsvorteile, wenn man eins über das andere verwendet? Gibt es noch etwas, das wir wissen sollten, wenn wir ES6-Module anstelle von Node verwenden würden?
Gibt es irgendwelche Leistungsvorteile, wenn man eins über das andere verwendet?
Beachten Sie, dass es noch keine JavaScript-Engine gibt, die ES6-Module nativ unterstützt. Du hast selbst gesagt, dass du Babel benutzt. Babel konvertiert die import
- und export
-Deklaration ohnehin standardmäßig in CommonJS (require
/module.exports
). Selbst wenn Sie die ES6-Modulsyntax verwenden, verwenden Sie CommonJS unter der Haube, wenn Sie den Code in Node ausführen.
Es gibt technische Unterschiede zwischen CommonJS- und ES6-Modulen, z. Mit CommonJS können Sie Module dynamisch laden. ES6 lässt dies nicht zu, dafür ist eine API in der Entwicklung .
Da ES6-Module Teil des Standards sind, würde ich sie verwenden.
Es gibt verschiedene Verwendungsmöglichkeiten, die Sie in Betracht ziehen sollten:
Benötigen:
require
s haben, werden sie einzeln geladen und verarbeitet.ES6-Importe:
Außerdem ist das Require-Modulsystem nicht standardbasiert. Es ist sehr unwahrscheinlich, dass dies zum Standard wird, wenn ES6-Module existieren. In Zukunft wird es native Unterstützung für ES6-Module in verschiedenen Implementierungen geben, was für die Leistung von Vorteil ist.
Die Hauptvorteile sind syntaktisch:
Es ist unwahrscheinlich, dass Sie mit ES6-Modulen Leistungsvorteile erzielen. Sie benötigen weiterhin eine zusätzliche Bibliothek, um die Module zu bündeln, auch wenn der Browser die ES6-Funktionen voll unterstützt.
Gibt es irgendwelche Leistungsvorteile, wenn man eins über das andere verwendet?
Die aktuelle Antwort lautet Nein, da keine der aktuellen Browser-Engines import/export
aus dem ES6-Standard implementiert.
Einige Vergleichstabellen http://kangax.github.io/compat-table/es6/ berücksichtigen dies nicht. Wenn Sie also fast alle Grüns für Chrome sehen, seien Sie vorsichtig. Das Schlüsselwort import
aus ES6 wurde nicht berücksichtigt.
Mit anderen Worten, aktuelle Browser-Engines, einschließlich V8, können neue JavaScript-Datei nicht über eine JavaScript-Direktive aus Haupt-JavaScript-Datei importieren.
(Möglicherweise sind wir nur noch ein paar Bugs entfernt oder Jahre entfernt, bis V8 dies gemäß der ES6-Spezifikation implementiert.)
Dieses Dokument ist das, was wir brauchen, und dieses Dokument ist das, was wir befolgen müssen.
Und der ES6-Standard besagte, dass die Modulabhängigkeiten vorhanden sein sollten, bevor wir das Modul wie in der Programmiersprache C lesen, in der wir (Header) .h
-Dateien hatten.
Dies ist eine gute und gut getestete Struktur, und ich bin mir sicher, dass die Experten, die den ES6-Standard erstellt haben, dies im Hinterkopf hatten.
Dies ermöglicht es Webpack oder anderen Paket-Bundlern, das Bundle in einigen speziellen Fällen zu optimieren und einige nicht benötigte Abhängigkeiten vom Bundle zu reduzieren. Aber in Fällen, in denen wir perfekte Abhängigkeiten haben, wird dies niemals passieren.
Es wird einige Zeit dauern, bis die native Unterstützung für import/export
aktiviert wird, und das Schlüsselwort require
wird für längere Zeit nirgendwo verfügbar sein.
Was ist require
?
Dies ist die node.js
Methode zum Laden von Modulen. ( https://github.com/nodejs/node )
Der Knoten verwendet Methoden auf Systemebene, um Dateien zu lesen. Darauf verlassen Sie sich grundsätzlich, wenn Sie require
verwenden. require
endet in einem Systemaufruf wie uv_fs_open
(abhängig vom Endsystem, Linux, Mac, Windows), um die JavaScript-Datei/das JavaScript-Modul zu laden.
Um dies zu überprüfen, versuchen Sie, Babel.js zu verwenden, und Sie werden feststellen, dass das Schlüsselwort import
in require
konvertiert wird.
Die Verwendung von ES6-Modulen kann nützlich sein, um Bäume zu schütteln. d.h. Webpack 2, Rollup (oder anderen Bundlern) ermöglichen, Codepfade zu identifizieren, die nicht verwendet/importiert werden, und es daher nicht in das resultierende Bundle zu schaffen. Dies kann die Dateigröße erheblich reduzieren, indem Sie Code eliminieren, den Sie nie benötigen. CommonJS ist jedoch standardmäßig im Lieferumfang enthalten, da Webpack et al. Keine Möglichkeit haben, zu wissen, ob er benötigt wird.
Dies erfolgt mithilfe einer statischen Analyse des Codepfads.
Zum Beispiel mit:
import { somePart } 'of/a/package';
... gibt dem Bundler einen Hinweis, dass package.anotherPart
nicht erforderlich ist (wenn es nicht importiert wird, kann es nicht verwendet werden - oder?), damit es nicht die Mühe macht, es zu bündeln.
Um dies für Webpack 2 zu aktivieren, müssen Sie sicherstellen, dass Ihr Transpiler keine CommonJS-Module ausspuckt. Wenn Sie das es2015
-Plug-In mit babel verwenden, können Sie es in Ihrem .babelrc
wie folgt deaktivieren:
{
"presets": [
["es2015", { modules: false }],
]
}
Rollup und andere funktionieren möglicherweise anders - sehen Sie sich die Dokumente an, wenn Sie interessiert sind.
Wenn es um asynchrones oder fauleres Laden geht, ist import ()
viel leistungsfähiger. Wenn wir die Komponente asynchron benötigen, verwenden wir import
auf asynchrone Weise wie in const
mit await
.
const module = await import('./module.js');
Oder wenn Sie require()
verwenden möchten,
const converter = require('./converter');
Was ist import()
ist eigentlich asynchron in der Natur. Wie von neehar venugopal in ReactConf erwähnt, können Sie damit Reaktionskomponenten für die clientseitige Architektur dynamisch laden.
Auch beim Routing ist es viel besser. Dies ist eine Besonderheit, die bewirkt, dass das Netzwerkprotokoll einen erforderlichen Teil herunterlädt, wenn der Benutzer eine Verbindung zu einer bestimmten Website mit einer bestimmten Komponente herstellt. z.B. Die Anmeldeseite vor dem Dashboard hat nicht alle Komponenten des Dashboards heruntergeladen. Da die aktuell, d. H. Die Anmeldekomponente, benötigt wird, wird diese nur heruntergeladen.
Gleiches gilt für export
: ES6 export
ist genau das gleiche wie für CommonJS module.exports
.
NOTE - Wenn Sie ein node.js-Projekt entwickeln, müssen Sie require()
als Knoten wirft einen Ausnahmefehler als invalid token 'import'
, wenn Sie import
verwenden. Daher unterstützt der Knoten keine Importanweisungen.
UPDATE - Wie von Dan Dascalescu vorgeschlagen: Seit Version 8.5.0 (veröffentlicht im September 2017) können Sie mit node --experimental-modules index.mjs
import
ohne Babel. Sie können (und sollten) auch Ihre npm-Pakete als natives ESModule veröffentlichen, mit Abwärtskompatibilität für den alten require
Weg.
Weitere Informationen zur Verwendung von asynchronen Importen finden Sie hier - https://www.youtube.com/watch?v=bb6RCrDaxhw
Das Wichtigste, was Sie wissen müssen, ist, dass ES6-Module tatsächlich ein offizieller Standard sind, CommonJS-Module (Node.js) jedoch nicht.
Im Jahr 2019 werden ES6-Module von 84% der Browser unterstützt. Während Node.js sie hinter ein - experimental-modules -Flag setzt, gibt es auch ein praktisches Knotenpaket mit dem Namen esm , das die Integration reibungslos macht.
Ein weiteres Problem, mit dem Sie wahrscheinlich zwischen diesen Modulsystemen zu kämpfen haben, ist die Codestelle. Node.js geht davon aus, dass sich die Quelle in einem node_modules
-Verzeichnis befindet, während die meisten ES6-Module in einer flachen Verzeichnisstruktur bereitgestellt werden. Diese sind nicht einfach zu vereinbaren, können aber durch Hacken Ihrer package.json
-Datei mit Skripten vor und nach der Installation durchgeführt werden. Hier ist ein Beispiel isomorphes Modul und ein Artikel , das erklärt, wie es funktioniert.
Ich persönlich benutze Import, weil wir die erforderlichen Methoden importieren können, Mitglieder durch den Import.
import {foo, bar} from "dep";
Dateiname: dep.js
export foo function(){};
export const bar = 22
Der Kredit geht an Paul Shan. Mehr Infos .