In einem Projekt, an dem ich zusammenarbeite, haben wir zwei Möglichkeiten, welches Modulsystem wir verwenden können:
- Importieren von Modulen mit
require
und Exportieren mitmodule.exports
undexports.foo
. - Importieren von Modulen mit ES6
import
und Exportieren mit ES6export
Gibt es Leistungsvorteile bei der Verwendung übereinander? Gibt es noch etwas, das wir wissen sollten, wenn wir ES6-Module über Node-Module verwenden würden?
javascript
node.js
ecmascript-6
babeljs
kpimov
quelle
quelle
node --experimental-modules index.mjs
import
Ermöglicht die Verwendung ohne Babel und funktioniert in Node 8.5.0+. Sie können (und sollten) Ihre npm-Pakete auch als natives ESModule veröffentlichen , mit Abwärtskompatibilität für den altenrequire
Weg.Antworten:
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
import
undexport
deklariert 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. B. können Sie mit CommonJS Module dynamisch laden. ES6 erlaubt dies nicht, aber dafür befindet sich eine API in der Entwicklung .
Da ES6-Module Teil des Standards sind, würde ich sie verwenden.
quelle
ES6 import
mit zu verwenden,require
aber sie funktionierten anders. CommonJS exportiert die Klasse selbst, während es nur eine Klasse gibt. ES6-Exporte, da es mehrere Klassen gibt, müssen Sie verwenden.ClassName
, um die exportierte Klasse abzurufen. Gibt es andere Unterschiede, die sich tatsächlich auf die Implementierungmodule.exports = ...;
ist äquivalent zuexport default ...
.exports.foo = ...
ist gleichbedeutend mitexport var foo = ...
;import
in CommonJS in Node transpiliert wird, das zusammen mit Webpack 2 / Rollup (und jedem anderen Bundler, der das Schütteln von ES6-Bäumen ermöglicht) verwendet wird, eine Datei erstellen kann, die erheblich kleiner ist als die entsprechenden Code-Node-Crunches durch die Verwendungrequire
genau aufgrund der Tatsache, dass ES6 eine statische Analyse von Import / Export ermöglicht. Während dies für Node (noch) keinen Unterschied macht, kann dies sicherlich der Fall sein, wenn der Code letztendlich als einzelnes Browser-Bundle angezeigt wird.Es gibt verschiedene Verwendungsmöglichkeiten / Funktionen, die Sie in Betracht ziehen sollten:
Benötigen:
require
s haben, werden diese einzeln geladen und verarbeitet.ES6-Importe:
Außerdem ist das Require-Modulsystem nicht standardbasiert. Es ist sehr unwahrscheinlich, dass es zum Standard wird, wenn ES6-Module existieren. In Zukunft wird es native Unterstützung für ES6-Module in verschiedenen Implementierungen geben, was hinsichtlich der Leistung vorteilhaft sein wird.
quelle
require
trotzdem ES6-Module , sodass Sie das Modulsystem und den Loader von Node trotzdem verwenden.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 die ES6-Funktionen im Browser vollständig unterstützt werden.
quelle
node --experimemntal-modules index.mjs
können Sieimport
ohne Babel verwenden. Sie können (und sollten) Ihre npm-Pakete auch als natives ESModule veröffentlichen, mit Abwärtskompatibilität für den altenrequire
Weg. Viele Browser unterstützen dynamische Importe auch nativ.Die aktuelle Antwort lautet "Nein", da keine der aktuellen Browser-Engines
import/export
den 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.
import
Schlüsselwort von ES6 wurde nicht berücksichtigt.Mit anderen Worten, aktuelle Browser-Engines einschließlich V8 können keine neue JavaScript-Datei aus der JavaScript-Hauptdatei über eine JavaScript-Direktive importieren .
(Möglicherweise sind wir nur noch wenige Fehler 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 sagte, dass die Modulabhängigkeiten vorhanden sein sollten, bevor wir das Modul lesen, wie in der Programmiersprache C, in der wir (Header-)
.h
Dateien hatten.Dies ist eine gute und gut getestete Struktur, und ich bin sicher, dass die Experten, die den ES6-Standard erstellt haben, dies berücksichtigt haben.
Dies ist , was Webpack oder anderes Paket Bündler ermöglicht das Bündel in einigen zu optimieren Sonderfällen und reduzieren einige Abhängigkeiten von dem Bündel , die nicht benötigt werden. Aber in Fällen, in denen wir perfekte Abhängigkeiten haben, wird dies niemals passieren.
Es wird einige Zeit
import/export
dauern, bis der native Support online geht, und dasrequire
Keyword wird lange Zeit nirgendwo hingehen.Was ist
require
?Auf diese
node.js
Weise können Module geladen werden. ( https://github.com/nodejs/node )Der Knoten verwendet Methoden auf Systemebene, um Dateien zu lesen. Darauf verlassen Sie sich bei der Verwendung grundsätzlich
require
.require
endet in einem Systemaufruf wieuv_fs_open
(abhängig vom Endsystem, Linux, Mac, Windows) zum Laden der JavaScript-Datei / des JavaScript-Moduls.Um zu überprüfen, ob dies der Fall ist, versuchen Sie, Babel.js zu verwenden, und Sie werden sehen, dass das
import
Schlüsselwort in konvertiert wirdrequire
.quelle
import
in einem Webpack 2 / Rollup-Erstellungsprozess kann möglicherweise die resultierende Dateigröße reduzieren, indem nicht verwendete Module / Codes durch Baumschütteln ersetzt werden, die andernfalls im endgültigen Bundle landen könnten. Kleinere Dateigröße = schneller zum Herunterladen = schneller zum Initiieren / Ausführen auf dem Client.import
Schlüsselwort nativ zulässt . Dies bedeutet auch, dass Sie keine andere JavaScript-Datei aus einer JavaScript-Datei importieren können. Aus diesem Grund können Sie die Leistungsvorteile dieser beiden nicht vergleichen. Aber natürlich können Tools wie Webpack1 / 2 oder Browserify mit Komprimierung umgehen. Sie sind Hals an Hals: gist.github.com/substack/68f8d502be42d5cd4942import
undexport
statische Erklärungen sind , die einen bestimmten Codepfad importieren, währendrequire
kann dynamisch sein und somit in Code bündeln , die nicht verwendet wird . Der Leistungsvorteil ist indirekt: Webpack 2 und / oder Rollup können möglicherweise zu kleineren Bundle-Größen führen, die schneller heruntergeladen werden können und daher für den Endbenutzer (eines Browsers) schneller erscheinen. Dies funktioniert nur, wenn der gesamte Code in ES6-Modulen geschrieben ist und daher Importe statisch analysiert werden können.import/export
wird konvertiertrequire
, gewährt. Was jedoch vor diesem Schritt passiert, kann als "Leistungssteigerung" angesehen werden. Beispiel: Wennlodash
es in ES6 geschrieben ist und Sieimport { omit } from lodash
, enthält das ultimative Bundle NUR "Auslassen" und nicht die anderen Dienstprogramme, während ein einfachesrequire('lodash')
alles importiert. Dadurch wird die Bundle-Größe erhöht, der Download dauert länger und die Leistung wird verringert. Dies gilt natürlich nur im Browserkontext.Die Verwendung von ES6-Modulen kann nützlich sein, um Bäume zu schütteln. Das heißt, Webpack 2, Rollup (oder andere Bundler) können Codepfade identifizieren, die nicht verwendet / importiert werden, und es daher nicht in das resultierende Bundle schaffen. Dies kann die Dateigröße erheblich reduzieren, indem Code eliminiert wird, den Sie nie benötigen. CommonJS wird jedoch standardmäßig gebündelt, da Webpack et al. Nicht wissen können, ob es benötigt wird.
Dies erfolgt durch statische Analyse des Codepfads.
Zum Beispiel mit:
... gibt dem Bundler einen Hinweis, der
package.anotherPart
nicht erforderlich ist (wenn er nicht importiert wird, kann er nicht verwendet werden - oder?), damit er ihn nicht bündelt.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.babelrc
wie folgt deaktivieren :Rollup und andere funktionieren möglicherweise anders - sehen Sie sich die Dokumente an, wenn Sie interessiert sind.
quelle
Wenn es um asynchrones oder vielleicht faules Laden geht,
import ()
ist es viel leistungsfähiger. Sehen Sie, wenn wir die Komponente asynchron benötigen, dann verwenden wirimport
sie auf asynchrone Weise wie bei derconst
Verwendung von Variablenawait
.Oder wenn Sie dann verwenden möchten
require()
,Die Sache ist
import()
tatsächlich asynchron in der Natur. Wie von neehar venugopal in ReactConf erwähnt , können Sie damit reaktionsfähige Komponenten für die clientseitige Architektur dynamisch laden.Auch beim Routing ist es viel besser. Dies ist die einzige Besonderheit, die das Netzwerkprotokoll zum Herunterladen eines erforderlichen Teils macht, wenn der Benutzer eine Verbindung zu einer bestimmten Website zu seiner bestimmten Komponente herstellt. Beispiel: Die Anmeldeseite vor dem Dashboard würde nicht alle Komponenten des Dashboards herunterladen. Da was aktuell benötigt wird, dh Anmeldekomponente, wird das nur heruntergeladen.
Gleiches gilt für
export
: ES6export
ist genau das gleiche wie für CommonJSmodule.exports
.HINWEIS - Wenn Sie ein node.js-Projekt entwickeln, müssen Sie es unbedingt verwenden,
require()
da der Knoten einen Ausnahmefehler auslöst, alsinvalid token 'import'
ob Sie ihn verwenden würdenimport
. Daher unterstützt der Knoten keine Importanweisungen.UPDATE - Wie von Dan Dascalescu vorgeschlagen : Seit Version 8.5.0 (veröffentlicht im September 2017)
node --experimental-modules index.mjs
können Sieimport
ohne Babel verwenden. Sie können (und sollten) Ihre npm-Pakete auch als natives ESModule veröffentlichen, mit Abwärtskompatibilität für den altenrequire
Weg.Weitere Informationen zur Verwendung von asynchronen Importen finden Sie hier - https://www.youtube.com/watch?v=bb6RCrDaxhw
quelle
Das Wichtigste 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 das Flag --experimental-modules setzt , gibt es auch ein praktisches Knotenpaket namens esm , das die Integration reibungslos macht.
Ein weiteres Problem, auf das Sie wahrscheinlich zwischen diesen Modulsystemen stoßen, ist die Code-Position. Node.js geht davon aus, dass die Quelle in einem
node_modules
Verzeichnis gespeichert ist, während die meisten ES6-Module in einer flachen Verzeichnisstruktur bereitgestellt werden. Diese sind nicht einfach zu vereinbaren, können jedoch durch Hacken Ihrerpackage.json
Datei mit Skripten vor und nach der Installation durchgeführt werden. Hier ist ein Beispiel für ein isomorphes Modul und ein Artikel, der erklärt, wie es funktioniert.quelle
Ich persönlich verwende Import, weil wir die erforderlichen Methoden importieren können, Mitglieder, indem wir Import verwenden.
Dateiname: dep.js.
Der Kredit geht an Paul Shan. Weitere Infos .
quelle
require
Art und Weise?const {a,b} = require('module.js');
funktioniert auch ... wenn Sie exportierena
undb
module.exports = { a: ()={}, b: 22 }
- Der zweite Teil von @BananaAcid antwortetAb dem ES6-Import wird der Export immer nach CommonJS kompiliert , sodass die Verwendung des einen oder anderen keinen Vorteil bringt . Die Verwendung von ES6 wird zwar empfohlen, da dies bei der Veröffentlichung der nativen Unterstützung durch Browser von Vorteil sein sollte. Der Grund dafür ist, dass Sie Partials aus einer Datei importieren können, während Sie mit CommonJS die gesamte Datei benötigen.
ES6 →
import, export default, export
CommonJS →
require, module.exports, exports.foo
Nachfolgend finden Sie eine allgemeine Verwendung dieser.
ES6-Exportstandard
ES6 exportiert mehrere und importiert mehrere
CommonJS module.exports
CommonJS module.exports multiple
quelle
Ich bin mir nicht sicher, warum (wahrscheinlich Optimierung - verzögertes Laden?) So funktioniert, aber ich habe festgestellt, dass
import
Code möglicherweise nicht analysiert wird, wenn importierte Module nicht verwendet werden.Was in einigen Fällen nicht zu erwarten ist.
Nehmen Sie die verhasste Foo-Klasse als unsere Beispielabhängigkeit.
foo.ts
Zum Beispiel:
index.ts
index.ts
index.ts
Auf der anderen Seite:
index.ts
quelle