Dans un projet sur lequel je collabore, nous avons deux choix sur le système de modules que nous pouvons utiliser:
- Importation de modules à l'aide
require
et exportation à l'aide demodule.exports
etexports.foo
. - Importation de modules à l'aide d'ES6
import
et exportation à l'aide d'ES6export
Y a-t-il des avantages en termes de performances à utiliser l'un par rapport à l'autre? Y a-t-il autre chose que nous devrions savoir si nous devions utiliser des modules ES6 sur des modules Node?
node --experimental-modules index.mjs
vous permet d'utiliserimport
sans Babel et fonctionne dans Node 8.5.0+. Vous pouvez (et devez) également publier vos packages npm en tant que ESModule natif , avec une compatibilité descendante pour l'anciennerequire
méthode.Réponses:
Gardez à l'esprit qu'il n'y a pas encore de moteur JavaScript qui supporte nativement les modules ES6. Vous avez dit vous-même que vous utilisez Babel. Babel convertit
import
etexport
déclare par défaut CommonJS (require
/module.exports
). Donc, même si vous utilisez la syntaxe du module ES6, vous utiliserez CommonJS sous le capot si vous exécutez le code dans Node.Il existe des différences techniques entre les modules CommonJS et ES6, par exemple CommonJS vous permet de charger les modules dynamiquement. ES6 ne le permet pas, mais il existe une API en développement pour cela .
Étant donné que les modules ES6 font partie de la norme, je les utiliserais.
la source
ES6 import
avecrequire
mais ils fonctionnaient différemment. CommonJS exporte la classe elle-même alors qu'il n'y a qu'une seule classe. Les exportations ES6 comme il existe plusieurs classes, vous devez donc utiliser.ClassName
pour obtenir la classe exportée. Y a-t-il d'autres différences quimodule.exports = ...;
est équivalent àexport default ...
.exports.foo = ...
est équivalent àexport var foo = ...
;import
vers CommonJS dans Node, utilisé avec Webpack 2 / Rollup (et tout autre bundle qui permet le tremblement de l'arborescence ES6), il est possible de se retrouver avec un fichier qui est nettement plus petit que le code équivalent. en utilisantrequire
exactement parce que ES6 permet une analyse statique des importations / exportations. Bien que cela ne fasse pas de différence pour Node (pour l'instant), c'est certainement le cas si le code finit par devenir un ensemble de navigateur unique.Il y a plusieurs utilisations / capacités que vous voudrez peut-être considérer:
Exiger:
require
s, ils sont chargés et traités un par un.Importations ES6:
De plus, le système de modules requis n'est pas basé sur des normes. Il est hautement improbable de devenir standard maintenant que les modules ES6 existent. À l'avenir, il y aura une prise en charge native des modules ES6 dans diverses implémentations, ce qui sera avantageux en termes de performances.
la source
require
toute façon, vous utilisez donc le système de modules et le chargeur de Node de toute façon.Les principaux avantages sont syntaxiques:
Il est peu probable que vous constatiez des avantages en termes de performances avec les modules ES6. Vous aurez toujours besoin d'une bibliothèque supplémentaire pour regrouper les modules, même s'il existe une prise en charge complète des fonctionnalités ES6 dans le navigateur.
la source
node --experimemntal-modules index.mjs
permet de l'utiliserimport
sans Babel. Vous pouvez (et devez) également publier vos packages npm en tant que ESModule natif, avec une compatibilité descendante pour l'anciennerequire
méthode. De nombreux navigateurs prennent également en charge les importations dynamiques en natif.La réponse actuelle est non, car aucun des moteurs de navigateur actuels n'est implémenté à
import/export
partir de la norme ES6.Certains tableaux de comparaison http://kangax.github.io/compat-table/es6/ ne prennent pas cela en compte, donc lorsque vous voyez presque tous les verts pour Chrome, faites juste attention.
import
mot-clé de ES6 n'a pas été pris en compte.En d'autres termes, les moteurs de navigateur actuels, y compris V8, ne peuvent pas importer de nouveau fichier JavaScript à partir du fichier JavaScript principal via une directive JavaScript.
(Il se peut que nous ne soyons encore qu'à quelques bugs ou dans des années jusqu'à ce que V8 implémente cela selon la spécification ES6.)
Ce document est ce dont nous avons besoin, et ce document est ce que nous devons obéir.
Et la norme ES6 a dit que les dépendances du module devraient être là avant de lire le module comme dans le langage de programmation C, où nous avions des
.h
fichiers (en-têtes) .Il s'agit d'une structure bonne et bien testée, et je suis sûr que les experts qui ont créé la norme ES6 avaient cela en tête.
C'est ce qui permet à Webpack ou à d'autres groupeurs de packages d'optimiser le bundle dans certains cas spéciaux et de réduire certaines dépendances du bundle qui ne sont pas nécessaires. Mais dans les cas où nous avons des dépendances parfaites, cela ne se produira jamais.
Il faudra un certain temps jusqu'à ce que
import/export
le support natif soit mis en ligne, et lerequire
mot - clé n'ira nulle part longtemps.Qu'est-ce que c'est
require
?C'est une
node.js
façon de charger des modules. ( https://github.com/nodejs/node )Le nœud utilise des méthodes au niveau du système pour lire les fichiers. Vous comptez essentiellement sur cela lors de l'utilisation
require
.require
se terminera par un appel système commeuv_fs_open
(dépend du système final, Linux, Mac, Windows) pour charger le fichier / module JavaScript.Pour vérifier que cela est vrai, essayez d'utiliser Babel.js, et vous verrez que le
import
mot - clé sera converti enrequire
.la source
import
dans un processus de construction Webpack 2 / Rollup peut potentiellement réduire la taille du fichier résultant en «secouant l'arborescence» des modules / codes inutilisés, qui pourraient sinon se retrouver dans le bundle final. Taille de fichier plus petite = téléchargement plus rapide = lancement / exécution plus rapide sur le client.import
mot - clé nativement. Ou cela signifie que vous ne pouvez pas importer un autre fichier JavaScript à partir d'un fichier JavaScript. C'est pourquoi vous ne pouvez pas comparer les avantages de performances de ces deux. Mais bien sûr, des outils comme Webpack1 / 2 ou Browserify peuvent gérer la compression. Ils sont au coude à coude: gist.github.com/substack/68f8d502be42d5cd4942import
etexport
sont des déclarations statiques qui importent un chemin de code spécifique, alors querequire
peut être dynamique et bundle ainsi dans le code qui est pas utilisé. L'avantage en termes de performances est indirect: Webpack 2 et / ou le correctif cumulatif peuvent potentiellement entraîner des tailles de bundle plus petites, plus rapides à télécharger et par conséquent plus intuitives pour l'utilisateur final (d'un navigateur). Cela ne fonctionne que si tout le code est écrit dans les modules ES6 et que les importations peuvent donc être analysées statiquement.import/export
est converti enrequire
, accordé. Mais ce qui se passe avant cette étape pourrait être considéré comme une amélioration des «performances». Exemple: silodash
est écrit en ES6 et vousimport { omit } from lodash
, le pack ultime contiendra UNIQUEMENT 'omis' et pas les autres utilitaires, alors qu'un simplerequire('lodash')
importera tout. Cela augmentera la taille du bundle, prendra plus de temps à télécharger et diminuera donc les performances. Bien sûr, cela n'est valable que dans un contexte de navigateur.L'utilisation de modules ES6 peut être utile pour «secouer l'arbre»; c'est-à-dire permettre à Webpack 2, Rollup (ou à d'autres bundlers) d'identifier les chemins de code qui ne sont pas utilisés / importés, et par conséquent ne pas en faire le bundle résultant. Cela peut réduire considérablement la taille de son fichier en éliminant le code dont vous n'aurez jamais besoin, mais avec CommonJS est fourni par défaut car Webpack et al n'ont aucun moyen de savoir s'il est nécessaire.
Cela se fait à l'aide d'une analyse statique du chemin du code.
Par exemple, en utilisant:
... donne au bundler un indice qui
package.anotherPart
n'est pas requis (s'il n'est pas importé, il ne peut pas être utilisé, n'est-ce pas?), donc cela ne dérangera pas de le regrouper.Pour l'activer pour Webpack 2, vous devez vous assurer que votre transpilateur ne crache pas de modules CommonJS. Si vous utilisez le
es2015
plug-in avec babel, vous pouvez le désactiver.babelrc
comme vous le souhaitez:Le cumul et d'autres peuvent fonctionner différemment - consultez les documents si vous êtes intéressé.
la source
En ce qui concerne le chargement asynchrone ou peut-être paresseux,
import ()
c'est beaucoup plus puissant. Voyez quand nous avons besoin du composant de manière asynchrone, puis nous l'utilisonsimport
d'une manière asynchrone comme dans l'const
utilisation de variablesawait
.Ou si vous souhaitez utiliser
require()
alors,La chose est en
import()
fait asynchrone dans la nature. Comme mentionné par neehar venugopal dans ReactConf , vous pouvez l'utiliser pour charger dynamiquement des composants React pour l'architecture côté client.De plus, c'est beaucoup mieux quand il s'agit de routage. C'est la seule chose spéciale qui fait que le journal réseau télécharge une partie nécessaire lorsque l'utilisateur se connecte à un site Web spécifique à son composant spécifique. Par exemple, la page de connexion avant que le tableau de bord ne télécharge pas tous les composants du tableau de bord. Parce que ce qui est nécessaire, c'est-à-dire le composant de connexion actuel, ce sera seulement téléchargé.
Il en va de même pour
export
: ES6export
sont exactement les mêmes que pour CommonJSmodule.exports
.REMARQUE - Si vous développez un projet node.js, vous devez alors strictement l'utiliser
require()
car le nœud générera une erreur d'exception commeinvalid token 'import'
si vous l'utilisiezimport
. Le nœud ne prend donc pas en charge les instructions d'importation.MISE À JOUR - Comme suggéré par Dan Dascalescu : depuis la v8.5.0 (sortie en septembre 2017),
node --experimental-modules index.mjs
vous permet de l'utiliserimport
sans Babel. Vous pouvez (et devez) également publier vos packages npm en tant que ESModule natif, avec une compatibilité descendante pour l'anciennerequire
méthode.Voir ceci pour plus de clairance sur l'utilisation des importations asynchrones - https://www.youtube.com/watch?v=bb6RCrDaxhw
la source
La chose la plus importante à savoir est que les modules ES6 sont, en effet, une norme officielle, contrairement aux modules CommonJS (Node.js).
En 2019, les modules ES6 sont pris en charge par 84% des navigateurs. Bien que Node.js les place derrière un indicateur --experimental-modules , il existe également un package de nœuds pratique appelé esm , qui facilite l'intégration.
Un autre problème que vous risquez de rencontrer entre ces systèmes de modules est l'emplacement du code. Node.js suppose que la source est conservée dans un
node_modules
répertoire, tandis que la plupart des modules ES6 sont déployés dans une structure de répertoire plate. Ce ne sont pas faciles à réconcilier, mais cela peut être fait en piratant votrepackage.json
fichier avec des scripts de pré et post-installation. Voici un exemple de module isomorphe et un article expliquant comment cela fonctionne.la source
J'utilise personnellement l'importation parce que, nous pouvons importer les méthodes requises, les membres en utilisant l'importation.
FileName: dep.js
Le mérite revient à Paul Shan. Plus d'infos .
la source
require
méthode?const {a,b} = require('module.js');
fonctionne aussi ... si vous exporteza
etb
module.exports = { a: ()={}, b: 22 }
- La deuxième partie de @BananaAcid répondÀ partir de maintenant l'importation ES6, l'exportation est toujours compilée vers CommonJS , il n'y a donc aucun avantage à utiliser l'une ou l'autre. Bien que l'utilisation d'ES6 soit recommandée car elle devrait être avantageuse lors de la prise en charge native des navigateurs. La raison en est que vous pouvez importer des partiels à partir d'un fichier alors qu'avec CommonJS, vous devez exiger tout le fichier.
ES6 →
import, export default, export
CommonJS →
require, module.exports, exports.foo
Ci-dessous est l'utilisation courante de ceux-ci.
Export par défaut ES6
ES6 exporte plusieurs et importe plusieurs
CommonJS module.exports
CommonJS module.exports multiple
la source
Je ne sais pas pourquoi (probablement optimisation - chargement paresseux?) Ça fonctionne comme ça, mais j'ai remarqué que le
import
code ne peut pas être analysé si les modules importés ne sont pas utilisés.Ce qui peut ne pas être un comportement attendu dans certains cas.
Prenez la classe Foo détestée comme exemple de dépendance.
foo.ts
Par exemple:
index.ts
index.ts
index.ts
D'autre part:
index.ts
la source