les modules natifs dans nodesjs
Published: 2022-11-01 04:21:16

Les modules CommonJS sont le moyen original d'empaqueter du code JavaScript pour Node.js. Node.js prend également en charge la norme de modules ECMAScript utilisée par les navigateurs et autres runtimes JavaScript.

Dans Node.js, chaque fichier est traité comme un module séparé. Par exemple, considérons un fichier nommé foo.js:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bop0sw7hutec6b0datxa.png)
Sur la première ligne, foo.jscharge le module circle.jsqui se trouve dans le même répertoire que foo.js.

Voici le contenu de circle.js:
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/35sfu5np7215yafpb5pn.png)

Le module circle.jsa exporté les fonctions area()et circumference(). Les fonctions et les objets sont ajoutés à la racine d'un module en spécifiant des propriétés supplémentaires sur l' exports objet spécial.

Les variables locales au module seront privées, car le module est encapsulé dans une fonction par Node.js (voir module wrapper ). Dans cet exemple, la variable PI est privée pour circle.js.

La module.exports propriété peut se voir attribuer une nouvelle valeur (telle qu'une fonction ou un objet).

Ci-dessous, bar.js utilise le squaremodule, qui exporte une classe Square :

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z9zx7ihzt03ui415q0u1.png)

Le squaremodule est défini dans square.js:
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jl21ob8slwqtdyhy3izg.png)

## Activation

Node.js a deux systèmes de modules : les modules CommonJS et les modules ECMAScript .

Par défaut, Node.js traitera les éléments suivants comme des modules CommonJS :

Fichiers avec une .cjsextension ;

Fichiers avec une .jsextension lorsque le fichier parent le plus proche package.js on contient un champ de niveau supérieur "type"avec une valeur de "commonjs".

Fichiers avec une .js extension lorsque le fichier parent le plus proche package.js on ne contient pas de champ de niveau supérieur "type". Les auteurs de packages doivent inclure le "type"champ, même dans les packages où toutes les sources sont CommonJS. Être explicite sur type le package facilitera les choses pour les outils de construction et les chargeurs afin de déterminer comment les fichiers du package doivent être interprétés.

Fichiers avec une extension qui n'est pas .mjs, .cjs, .json, .node, ou .js (lorsque le fichier parent le plus proche package.jsoncontient un champ de niveau supérieur "type"avec une valeur de "module", ces fichiers seront reconnus comme modules CommonJS uniquement s'ils sont required, pas lorsqu'ils sont utilisés comme la commande -ligne point d'entrée du programme).
L'appel require() utilise toujours le chargeur de module CommonJS. L'appel import() utilise toujours le chargeur de module ECMAScript.

## Accéder au module principal

Lorsqu'un fichier est exécuté directement à partir de Node.js, require.main est défini sur son module. Cela signifie qu'il est possible de déterminer si un fichier a été exécuté directement en testant require.main === module.

Pour un fichier foo.js, ce sera trues'il est exécuté via node foo.js, mais falses' il est exécuté par require('./foo').

Lorsque le point d'entrée n'est pas un module CommonJS, require.main est undefined, et que le module principal est hors de portée.

## Mise en cache

Les modules sont mis en cache après leur premier chargement. Cela signifie (entre autres choses) que chaque appel à require('foo')obtiendra exactement le même objet renvoyé, s'il résout le même fichier.

À condition qu'il require.cache ne soit pas modifié, plusieurs appels à require('foo') ne provoqueront pas l'exécution multiple du code du module. C'est une caractéristique importante. Avec lui, les objets "partiellement terminés" peuvent être renvoyés, permettant ainsi aux dépendances transitives d'être chargées même lorsqu'elles provoqueraient des cycles.

Pour qu'un module exécute du code plusieurs fois, exportez une fonction et appelez cette fonction.

## Avertissements concernant la mise en cache des modules

Les modules sont mis en cache en fonction de leur nom de fichier résolu. Étant donné que les modules peuvent être résolus en un nom de fichier différent en fonction de l'emplacement du module appelant (chargement à partir de node_modulesdossiers),
 il n'est pas garanti qu'il require('foo')renverra toujours exactement le même objet, s'il devait être résolu en différents fichiers.

De plus, sur les systèmes de fichiers ou les systèmes d'exploitation insensibles à la casse, différents noms de fichiers résolus peuvent pointer vers le même fichier, mais le cache les traitera toujours comme des modules différents et rechargera le fichier plusieurs fois. Par exemple, require('./foo')and renvoie deux objets différents, que and require('./FOO')soient ou non le même fichier../foo./FOO


Node.js a plusieurs modules compilés dans le binaire. Ces modules sont décrits plus en détail ailleurs dans cette documentation.

Les modules principaux sont définis dans la source Node.js et se trouvent dans le lib/dossier.

Les modules principaux peuvent être identifiés à l'aide du node:préfixe, auquel cas il contourne le requirecache. Par exemple, require('node:http')renverra toujours le module HTTP intégré, même s'il existe une require.cacheentrée portant ce nom.

Certains modules de base sont toujours chargés préférentiellement si leur identifiant est passé à require(). Par exemple, require('http')renverra toujours le module HTTP intégré, même s'il existe un fichier portant ce nom. La liste des modules principaux qui peuvent être chargés sans utiliser le node:préfixe est exposée sous la forme module.builtinModules.

## Cycles

Lorsqu'il y a des require() appels circulaires, un module peut ne pas avoir fini de s'exécuter lorsqu'il est renvoyé.

Considérez cette situation  dans a.js :


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lza7edpkarithcw0bdic.png)

et celle-ci  b.js: 


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wx7igbycrjlhk05g6j4x.png)

et en dernier celui dans main.js : 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n501bmoutwa8g2h6dqi0.png)

Lorsque main.js  charges a.js, puis a.js à leur tour charges b.js. À ce stade, b.js essaie de charger a.js. Afin d'éviter une boucle infinie, une copie inachevée de l' a.js objet exports est renvoyée au b.js module. b.js puis termine le chargement, et son exports objet est fourni au a.js module.

Au moment où main.js les deux modules ont été chargés, ils sont tous les deux terminés. La sortie de ce programme serait donc  si vous lancer ce programme on aura une telle resultat : "$ node main.js

## main starting
a starting
b starting
dans  b, a.done = false
b done
dans a, b.done = true
a done
in main, a.done = true, b.done = true"

## Modules de fichiers

Si le nom de fichier exact n'est pas trouvé, alors Node.js tentera de charger le nom de fichier requis avec les extensions ajoutées : .js, .json et enfin .node. Lors du chargement d'un fichier qui a une extension différente (par exemple .cjs), son nom complet doit être passé à require(), y compris son extension de fichier (par exemple require('./file.cjs')).

.json les fichiers sont analysés comme des fichiers texte JSON, 
.node les fichiers sont interprétés comme des modules complémentaires compilés chargés avec process.dlopen(). Les fichiers utilisant une autre extension (ou aucune extension du tout) sont analysés comme des fichiers texte JavaScript. Reportez-vous à la section Détermination du système de module pour comprendre quel objectif d'analyse sera utilisé.

Un module obligatoire préfixé par '/'est un chemin absolu vers le fichier. Par exemple, require('/home/marco/foo.js')chargera le fichier à /home/marco/foo.js.

Un module obligatoire préfixé par './'est relatif au fichier appelant require(). C'est-à-dire circle.jsqu'il doit se trouver dans le même répertoire que foo.jspour require('./circle')le trouver.

Sans début '/', './', ou '../'pour indiquer un fichier, le module doit soit être un module principal, soit être chargé à partir d'un node_modulesdossier.

Si le chemin donné n'existe pas, require()génère une MODULE_NOT_FOUNDerreur.
Dossiers en tant que modules#
Stabilité : 3 - Legacy : utilisez plutôt les exportations de sous-chemins ou les importations de sous -chemins .
Il existe trois manières de passer un dossier en require()tant qu'argument.

La première consiste à créer un package.jsonfichier à la racine du dossier, qui spécifie un mainmodule. Un exemple package.jsonde fichier pourrait ressembler à ceci :

{ "name" : "some-library",
  "main" : "./lib/some-library.js" }
Si c'était dans un dossier à ./some-library, alors require('./some-library')tenterait de charger ./some-library/lib/some-library.js.

Si aucun package.jsonfichier n'est présent dans le répertoire, ou si l' "main"entrée est manquante ou ne peut pas être résolue, alors Node.js tentera de charger un fichier index.jsor index.nodeà partir de ce répertoire. Par exemple, s'il n'y avait pas package.jsonde fichier dans l'exemple précédent, alors require('./some-library')tenterait de charger :

./some-library/index.js
./some-library/index.node
Si ces tentatives échouent, Node.js signalera le module entier comme manquant avec l'erreur par défaut :

Error: Cannot find module 'some-library'
Dans les trois cas ci-dessus, un import('./some-library')appel entraînerait une ERR_UNSUPPORTED_DIR_IMPORTerreur. L'utilisation d'exportations de sous-chemins de packages ou d'importations de sous-chemins peut fournir les mêmes avantages d'organisation de confinement que les dossiers en tant que modules, et fonctionne à la fois pour requireet import.

Chargement à partir de node_modulesdossiers#
Si l'identifiant de module transmis à require()n'est pas un module principal et ne commence pas par '/', '../', ou './', alors Node.js démarre dans le répertoire du module actuel, ajoute /node_modules, et tente de charger le module à partir de cet emplacement. Node.js ne s'ajoutera pas node_modulesà un chemin se terminant déjà par node_modules.

S'il n'y est pas trouvé, il se déplace vers le répertoire parent, et ainsi de suite, jusqu'à ce que la racine du système de fichiers soit atteinte.

Par exemple, si le fichier '/home/ry/projects/foo.js'appelé require('bar.js'), alors Node.js cherchera dans les emplacements suivants, dans cet ordre :

/home/ry/projects/node_modules/bar.js
/home/ry/node_modules/bar.js
/home/node_modules/bar.js
/node_modules/bar.js
Cela permet aux programmes de localiser leurs dépendances, afin qu'elles n'entrent pas en conflit.

Il est possible d'exiger des fichiers spécifiques ou des sous-modules distribués avec un module en incluant un suffixe de chemin après le nom du module. Par exemple require('example-module/path/to/file'), résoudrait path/to/file par rapport à l'endroit où example-modulese trouve. Le chemin suffixé suit la même sémantique de résolution de module.

Chargement à partir des dossiers globaux#
Si la NODE_PATHvariable d'environnement est définie sur une liste de chemins absolus délimités par deux-points, Node.js recherchera ces chemins pour les modules s'ils ne sont pas trouvés ailleurs.

Sous Windows, NODE_PATHest délimité par des points-virgules ( ;) au lieu de deux-points.

NODE_PATHa été créé à l'origine pour prendre en charge le chargement de modules à partir de différents chemins avant que l' algorithme de résolution de module actuel ne soit défini.

NODE_PATHest toujours pris en charge, mais est moins nécessaire maintenant que l'écosystème Node.js a établi une convention pour localiser les modules dépendants. Parfois, les déploiements qui s'appuient sur NODE_PATHprésentent un comportement surprenant lorsque les utilisateurs ignorent ce qui NODE_PATHdoit être défini. Parfois, les dépendances d'un module changent, entraînant le chargement d'une version différente (ou même d'un module différent) lors de la NODE_PATHrecherche.

De plus, Node.js recherchera dans la liste suivante de GLOBAL_FOLDERS :

1:$HOME/.node_modules
2 :$HOME/.node_libraries
3 :$PREFIX/lib/node
Où $HOMEest le répertoire personnel de l'utilisateur et $PREFIXest le Node.js configuré node_prefix.

Ce sont principalement pour des raisons historiques.

Il est fortement recommandé de placer les dépendances dans le node_modules dossier local. Ceux-ci seront chargés plus rapidement et de manière plus fiable.

L'enveloppe du module#
Avant que le code d'un module ne soit exécuté, Node.js l'enveloppera avec un wrapper de fonction qui ressemble à ceci :

(function(exports, require, module, __filename, __dirname) {
// Module code actually lives in here
});
En faisant cela, Node.js réalise plusieurs choses :

Il conserve les variables de niveau supérieur (définies avec var, constou let) limitées au module plutôt qu'à l'objet global.
Il est utile de fournir des variables d'aspect global qui sont en fait spécifiques au module, telles que :
Les objets moduleet exportsque l'implémenteur peut utiliser pour exporter des valeurs à partir du module.
Les variables de commodité __filenameet __dirname, contenant le nom de fichier absolu du module et le chemin du répertoire.
La portée du module#
__dirname#
Ajouté dans : v0.1.27
<chaîne>
Le nom du répertoire du module actuel. C'est la même chose que path.dirname()le __filename.

Exemple : node example.jspartir de/Users/mjr

console.log(__dirname);
// Prints: /Users/mjr
console.log(path.dirname(__filename));
// Prints: /Users/mjr
__filename#
Ajouté dans : v0.0.1
<chaîne>
Le nom de fichier du module actuel. Il s'agit du chemin absolu du fichier de module actuel avec les liens symboliques résolus.

Pour un programme principal, ce n'est pas nécessairement le même que le nom de fichier utilisé dans la ligne de commande.

Voir __dirnamepour le nom du répertoire du module courant.

Exemples:

Courant node example.jsde/Users/mjr

console.log(__filename);
// Prints: /Users/mjr/example.js
console.log(__dirname);
// Prints: /Users/mjr
Étant donné deux modules : aet b, où best une dépendance de aet il existe une structure de répertoires de :

/Users/mjr/app/a.js
/Users/mjr/app/node_modules/b/b.js
Les références à __filenameinside b.jsreviendront /Users/mjr/app/node_modules/b/b.jstandis que les références à __filenamewithin a.jsreviendront /Users/mjr/app/a.js.

exports#
Ajouté dans : v0.1.12
<Objet>
Une référence à la module.exportsqui est plus courte à taper. Voir la section sur le raccourci d'exportation pour plus de détails sur quand l'utiliser exportset quand l'utiliser module.exports.

module#
Ajouté dans : v0.1.16
<module>
Une référence au module actuel, voir la section sur l' moduleobjet . En particulier, module.exportsest utilisé pour définir ce qu'un module exporte et met à disposition via require().

require(id)#
Ajouté dans : v0.1.13
id <string> nom ou chemin du module
Renvoie : <tout> contenu de module exporté
Utilisé pour importer des modules, JSONet des fichiers locaux. Les modules peuvent être importés depuis node_modules. Les modules locaux et les fichiers JSON peuvent être importés à l'aide d'un chemin relatif (par exemple ./, ./foo, ./bar/baz, ../foo) qui sera résolu par rapport au répertoire nommé par __dirname(si défini) ou au répertoire de travail actuel. Les chemins relatifs du style POSIX sont résolus de manière indépendante du système d'exploitation, ce qui signifie que les exemples ci-dessus fonctionneront sous Windows de la même manière qu'ils le feraient sur les systèmes Unix.

// Importing a local module with a path relative to the `__dirname` or current
// working directory. (On Windows, this would resolve to .\path\myLocalModule.)
const myLocalModule = require('./path/myLocalModule');

// Importing a JSON file:
const jsonData = require('./path/filename.json');

// Importing a module from node_modules or Node.js built-in module:
const crypto = require('node:crypto');
require.cache#
Ajouté dans : v0.3.0
<Objet>
Les modules sont mis en cache dans cet objet lorsqu'ils sont nécessaires. En supprimant une valeur clé de cet objet, la suivante requirerechargera le module. Cela ne s'applique pas aux addons natifs , pour lesquels le rechargement entraînera une erreur.

L'ajout ou le remplacement d'entrées est également possible. Ce cache est vérifié avant les modules natifs et si un nom correspondant à un module natif est ajouté au cache, seuls node:les appels require préfixés recevront le module natif. A utiliser avec précaution !

const assert = require('node:assert');
const realFs = require('node:fs');

const fakeFs = {};
require.cache.fs = { exports: fakeFs };

assert.strictEqual(require('node:fs'), fakeFs);
assert.strictEqual(require('node:fs'), realFs);

require.extensions#
Ajouté dans : v0.3.0 Obsolète depuis : v0.10.6
Stabilité : 0 - Obsolète
<Objet>
Instruire requiresur la façon de gérer certaines extensions de fichiers.

Traiter les fichiers avec l'extension .sjscomme .js:

require.extensions['.sjs'] = require.extensions['.js'];
Obsolète. Dans le passé, cette liste était utilisée pour charger des modules non JavaScript dans Node.js en les compilant à la demande. Cependant, dans la pratique, il existe de bien meilleures façons de le faire, comme charger des modules via un autre programme Node.js, ou les compiler en JavaScript à l'avance.

Évitez d'utiliser require.extensions. L'utilisation peut provoquer des bogues subtils et la résolution des extensions devient plus lente avec chaque extension enregistrée.

require.main

Ajouté dans : v0.1.17
<module> | <indéfini>

L' Module objet représentant le script d'entrée chargé lors du lancement du processus Node.js, ou undefined si le point d'entrée du programme n'est pas un module CommonJS. Voir "Accéder au module principal" .

En entry.js script :

console.log(require.main);
node entry.js
Module {
  id: '.',
  path: '/absolute/path/to',
  exports: {},
  filename: '/absolute/path/to/entry.js',
  loaded: false,
  children: [],
  paths:
   [ '/absolute/path/to/node_modules',
     '/absolute/path/node_modules',
     '/absolute/node_modules',
     '/node_modules' ] }


L' moduleobjet#
Ajouté dans : v0.1.16
<Objet>
Dans chaque module, la modulevariable libre est une référence à l'objet représentant le module courant. Pour plus de commodité, module.exportsest également accessible via le exportsmodule-global. modulen'est pas réellement global mais plutôt local pour chaque module.

module.children#
Ajouté dans : v0.1.16
<module[]>
Les objets modules requis pour la première fois par celui-ci.

module.exports#
Ajouté dans : v0.1.16
<Objet>
L' module.exportsobjet est créé par le Modulesystème. Parfois, ce n'est pas acceptable; beaucoup veulent que leur module soit une instance d'une classe. Pour ce faire, affectez l'objet d'exportation souhaité à module.exports. L'affectation de l'objet souhaité à exportsne fera que relier la exportsvariable locale, ce qui n'est probablement pas ce qui est souhaité.

Par exemple, supposons que nous créons un module appelé a.js:

const EventEmitter = require('node:events');

module.exports = new EventEmitter();

// Do some work, and after some time emit
// the 'ready' event from the module itself.
setTimeout(() => {
  module.exports.emit('ready');
}, 1000);
Ensuite, dans un autre fichier, nous pourrions faire :

const a = require('./a');
a.on('ready', () => {
  console.log('module "a" is ready');
});
L'affectation à module.exportsdoit être effectuée immédiatement. Cela ne peut pas être fait dans les rappels. Cela ne fonctionne pas:

x.js:

setTimeout(() => {
  module.exports = { a: 'hello' };
}, 0);
y.js:

const x = require('./x');
console.log(x.a);
exportsraccourci#
Ajouté dans : v0.1.16
La exportsvariable est disponible dans la portée de niveau fichier d'un module et reçoit la valeur de module.exportsavant l'évaluation du module.

Il permet un raccourci, de sorte qu'il module.exports.f = ...peut être écrit plus succinctement comme exports.f = .... Cependant, sachez que comme toute variable, si une nouvelle valeur est affectée à exports, elle n'est plus liée à module.exports:

module.exports.hello = true; // Exported from require of module
exports = { hello: false };  // Not exported, only available in the module
Lorsque la module.exportspropriété est entièrement remplacée par un nouvel objet, il est courant de réaffecter également exports:

module.exports = exports = function Constructor() {
  // ... etc.
};
Pour illustrer le comportement, imaginez cette implémentation hypothétique de require(), qui est assez similaire à ce qui est réellement fait par require():

function require(/* ... */) {
  const module = { exports: {} };
  ((module, exports) => {
    // Module code here. In this example, define a function.
    function someFunc() {}
    exports = someFunc;
    // At this point, exports is no longer a shortcut to module.exports, and
    // this module will still export an empty default object.
    module.exports = someFunc;
    // At this point, the module will now export someFunc, instead of the
    // default object.
  })(module, module.exports);
  return module.exports;
}
module.filename#
Ajouté dans : v0.1.16
<chaîne>
Le nom de fichier entièrement résolu du module.

module.id#
Ajouté dans : v0.1.16
<chaîne>
L'identifiant du module. Il s'agit généralement du nom de fichier entièrement résolu.

module.isPreloading#
Ajouté dans : v15.4.0
Tapez : <booléen> true si le module est en cours d'exécution pendant la phase de préchargement de Node.js.
module.loaded#
Ajouté dans : v0.1.16
<booléen>
Indique si le module a fini de se charger ou s'il est en train de se charger.

module.parent#
Ajouté dans : v0.1.16 Obsolète depuis : v14.6.0, v12.19.0
Stabilité : 0 - Obsolète : veuillez utiliser require.mainet à la module.childrenplace.
<module> | <null> | <indéfini>
Le module qui a d'abord requis celui-ci, ou nullsi le module courant est le point d'entrée du processus courant, ou undefinedsi le module a été chargé par quelque chose qui n'est pas un module CommonJS (EX : REPL ou import).

module.path#
Ajouté dans : v11.14.0
<chaîne>
Le nom du répertoire du module. C'est généralement le même que le path.dirname()de module.id.

module.paths#
Ajouté dans : v0.4.0
<chaîne[]>
Les chemins de recherche du module.

module.require(id)#
Ajouté dans : v0.5.1
id <chaîne>
Renvoie : <tout> contenu de module exporté
La module.require()méthode fournit un moyen de charger un module comme s'il require() était appelé depuis le module d'origine.

Pour ce faire, il est nécessaire d'obtenir une référence à l' moduleobjet. Étant donné que require()renvoie le module.exports, et que le module n'est généralement disponible que dans le code d'un module spécifique, il doit être explicitement exporté pour pouvoir être utilisé.

L' Moduleobjet#
Cette section a été déplacée vers Modules : module module de base .

module.builtinModules
module.createRequire(filename)
module.syncBuiltinESMExports()