Node.js 13.2.0 est livré avec le support ECMAScript pour les modules connus pour leur syntaxe d'importation et d'exportation. Auparavant, cette fonctionnalité était derrière l' --experimental-modules
, qui n'est plus nécessaire. Cependant, la mise en œuvre est encore expérimentale et est sujette à changement.
D'un traducteur: cette fonctionnalité tant attendue va enfin nous permettre d'utiliser la syntaxe modulaire standard déjà disponible dans les navigateurs modernes, et maintenant aussi dans Node.js sans drapeaux et transpilers
Activation
Node.js traitera le code en tant que modules ES dans les cas suivants:
- Fichiers avec l'extension
.mjs
- Fichiers avec l'extension
.js
ou sans extension du tout, à condition que le package.json
plus proche contienne la valeur "type": "module"
- Code transmis via l'argument
—-eval
ou STDIN, avec l'indicateur —-input-type=module
Dans tous les autres cas, le code sera considéré comme CommonJS. Cela s'applique aux fichiers .js
sans "type": "module"
dans le package.json
le plus proche et au code transmis via la ligne de commande sans spécifier --input-type
. Ceci est fait afin de maintenir la compatibilité descendante. Cependant, comme nous avons maintenant deux types de modules, CommonJS et ES, il sera préférable de spécifier explicitement le type de modules.
Vous pouvez explicitement marquer votre code comme CommonJS avec les fonctionnalités suivantes:
- Fichiers avec l'extension
.cjs
- Fichiers avec l'extension
.js
ou sans extension du tout, à condition que le "type": "“commonjs”"
le plus proche contienne la valeur "type": "“commonjs”"
- Code transmis via l'argument
--eval
ou STDIN avec l'indicateur explicite --input-type=commonjs
Pour en savoir plus sur ces fonctionnalités, consultez les sections de documentation "Étendue du package et extensions de fichier" et --input-type
Importation et exportation de syntaxe
Dans le contexte du module ES, vous pouvez utiliser l' import
en pointant vers d'autres fichiers Javascript. Ils peuvent être spécifiés dans l'un des formats suivants:
- URL relative:
"./file.mjs"
- URL c absolue
file://
, par exemple, "file:///opt/app/file.mjs"
- Nom du paquet:
"es-module-package"
- Le chemin d'accès au fichier à l'intérieur du package:
"es-module-package/lib/file.mjs"
Dans les importations, vous pouvez utiliser les valeurs par défaut ( import _ from "es-module-package"
) et nommées ( import { shuffle } from "es-module-package"
), ainsi que tout importer comme un seul espace de noms ( import * as fs from "fs"
). Tous les packages Node.js intégrés, comme fs
ou path
, prennent en charge les trois types d'importations.
Les importations qui pointent vers du code CommonJS (c'est-à-dire tout le JavaScript actuel écrit pour Node.js à l' require
et module.exports
) ne peuvent utiliser que l'option par défaut ( import _ from "commonjs-package"
).
L'importation d'autres formats de fichiers tels que JSON et WASM reste expérimentale et nécessite respectivement les indicateurs --experimental-json-modules
et --experimental-wasm-modules
. Cependant, vous pouvez télécharger ces fichiers à l'aide de l'API module.createRequire
, qui est disponible sans indicateurs supplémentaires.
Dans vos modules ES, vous pouvez utiliser le mot-clé d'exportation pour exporter les valeurs par défaut et nommées.
Les expressions dynamiques avec import()
peuvent être utilisées pour charger des modules ES à partir du code CommonJS ou ES. Notez que import()
ne renvoie pas un module mais sa promesse (Promise).
import.meta.url
est import.meta.url
disponible dans les modules, qui contient l'URL absolue du module ES actuel.
Fichiers et nouveau champ "type" dans package.json
Ajoutez "type": "module"
au package.json de votre projet et Node.js commencera à percevoir tous les fichiers .js
de votre projet comme des modules ES.
Si certains fichiers de votre projet utilisent toujours CommonJS et que vous ne pouvez pas migrer l'ensemble du projet à la fois, vous pouvez soit utiliser l'extension .cjs
pour ce code, soit le placer dans un répertoire séparé et ajouter package.json
contenant le { "type": "commonjs" }
, qui indique à Node.js qu'il doit être traité comme CommonJS.
Pour chaque fichier téléchargé, Node.js recherchera package.json
dans le répertoire qui le contient, puis un niveau plus haut, et ainsi de suite jusqu'à ce qu'il atteigne le répertoire racine. Ce mécanisme est similaire à la façon dont Babel .babelrc
fichiers Babel .babelrc
. Cette approche permet à Node.js d'utiliser package.json
comme source de diverses métadonnées sur le package et la configuration, de la même manière que cela fonctionne déjà dans Babel et d'autres outils.
Nous recommandons à tous les développeurs de packages de spécifier un champ de type
, même si commonjs
est écrit.
Les points d'entrée du package et le champ "exports" dans package.json
Nous avons maintenant deux champs pour spécifier le point d'entrée dans le package: main
et exports
. Le champ main
est pris en charge par toutes les versions de Node.js, mais ses capacités sont limitées: avec lui, vous ne pouvez définir qu'un seul point d'entrée principal dans le package. Le nouveau champ d' exports
vous permet également de définir le point d'entrée principal, ainsi que des chemins supplémentaires. Cela fournit une encapsulation supplémentaire pour les packages où seuls les chemins d' exports
explicites sont disponibles pour l'importation depuis l'extérieur du package. exports
s'appliquent aux deux types de modules, CommonJS et ES, qu'ils soient utilisés via require
ou import
.
Cette fonctionnalité permettra aux importations pkg/feature
type de pkg/feature
de pointer vers un chemin réel comme ./node_modules/pkg/esm/feature.js
. En outre, Node.js pkg/esm/feature.js
une erreur si l'importation fait référence à pkg/esm/feature.js
qui n'est pas spécifié dans les exports
.
Une fonctionnalité supplémentaire, encore expérimentale, d' exportations conditionnelles offre la possibilité d'exporter différents fichiers pour différents environnements. Cela permettra au package de donner le code CommonJS à appeler require("pkg")
et le code du module ES à importer via l' import "pkg"
, bien que l'écriture d'un tel package ne soit pas sans poser d'autres problèmes . Vous pouvez activer les exportations conditionnelles avec l' —-experimental-conditional-exports
.
Le rake principal des nouveaux modules
Extensions de fichiers requises
Lorsque vous utilisez des importations, vous devez spécifier l'extension de fichier. Lors de l'importation d'un fichier d'index à partir d'un répertoire, vous devez également spécifier complètement le chemin d'accès au fichier, c'est-à-dire "./startup/index.js".
Ce comportement coïncide avec le fonctionnement des importations dans les navigateurs lors de l'accès à un serveur standard sans configuration supplémentaire.
module.exports
, exports
, module.exports
, __filename
, __dirname
Ces valeurs de CommonJS ne sont pas disponibles dans le contexte des modules ES. Cependant, require
peut être importé dans le module ES via module.createRequire()
. Les équivalents __filename
et __dirname
peuvent être obtenus auprès de import.meta.url
.
Création de packages
Pour le moment, nous recommandons aux auteurs de packages d'utiliser des modules entièrement CommonJS ou entièrement ES pour leurs projets Node.js. Le groupe de travail sur les modules pour Node.js continue de chercher des moyens d'améliorer la prise en charge des packages doubles, avec CommonJS pour les utilisateurs hérités et les modules ES pour les nouveaux. Les exportations conditionnelles sont désormais expérimentales et nous espérons déployer cette fonctionnalité ou son alternative d'ici fin janvier 2020, voire plus tôt.
Pour en savoir plus à ce sujet, consultez nos exemples et recommandations pour la création de packages de modules CommonJS / ES doubles.
Que se passera-t-il ensuite
Chargeurs. Les travaux se poursuivent sur l'API pour l'écriture de chargeurs personnalisés, pour l'implémentation de la transpiration des modules dans le runtime, la redéfinition des chemins d'importation (packages ou fichiers individuels) et l'instrumentation du code. L'API expérimentale, accessible sous l' —-experimental-loader
, sera sujette à d'importantes modifications avant d'être supprimée de l'indicateur.
Deux packages de modules CommonJS / ES. Nous voulons fournir un moyen standard de publier un package qui peut être utilisé à la fois via require
dans CommonJS et via l' import
dans les modules ES. Nous avons plus d'informations à ce sujet dans la documentation . Nous prévoyons d'achever les travaux et de nous retirer du drapeau d'ici la fin de janvier 2020, sinon plus tôt.
C'est tout! Nous espérons que la prise en charge d'ECMAScript pour les modules rapproche Node.js des normes JavaScript et apporte de nouvelles fonctionnalités de compatibilité à travers tout l'écosystème JavaScript. Le flux de travail pour améliorer la prise en charge des modules se fait publiquement ici: https://github.com/nodejs/modules .