Modules : modules CommonJS
[Stable : 2 - Stable]
Stable : 2 Stabilité : 2 - Stable
Les modules CommonJS constituent la méthode originale d’empaquetage du code JavaScript pour Node.js. Node.js prend également en charge la norme des modules ECMAScript utilisée par les navigateurs et autres environnements d’exécution JavaScript.
Dans Node.js, chaque fichier est traité comme un module distinct. Par exemple, considérons un fichier nommé foo.js
:
const circle = require('./circle.js')
console.log(`L’aire d’un cercle de rayon 4 est ${circle.area(4)}`)
Sur la première ligne, foo.js
charge le module circle.js
qui se trouve dans le même répertoire que foo.js
.
Voici le contenu de circle.js
:
const { PI } = Math
exports.area = r => PI * r ** 2
exports.circumference = r => 2 * PI * r
Le module circle.js
a 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’objet exports
spécial.
Les variables locales au module seront privées, car le module est encapsulé dans une fonction par Node.js (voir encapsulation de module). Dans cet exemple, la variable PI
est privée pour circle.js
.
La propriété module.exports
peut se voir assigner une nouvelle valeur (telle qu’une fonction ou un objet).
Dans le code suivant, bar.js
utilise le module square
, qui exporte une classe Square :
const Square = require('./square.js')
const mySquare = new Square(2)
console.log(`L’aire de mySquare est ${mySquare.area()}`)
Le module square
est défini dans square.js
:
// L’affectation à exports ne modifiera pas le module, il faut utiliser module.exports
module.exports = class Square {
constructor(width) {
this.width = width
}
area() {
return this.width ** 2
}
}
Le système de modules CommonJS est implémenté dans le module principal module
.
Activation
Node.js possède deux systèmes de modules : les modules CommonJS et les modules ECMAScript.
Par défaut, Node.js traitera ce qui suit comme des modules CommonJS :
- Les fichiers avec une extension
.cjs
; - Les fichiers avec une extension
.js
lorsque le fichierpackage.json
parent le plus proche contient un champ de niveau supérieur"type"
avec la valeur"commonjs"
. - Les fichiers avec une extension
.js
ou sans extension, lorsque le fichierpackage.json
parent le plus proche ne contient pas de champ de niveau supérieur"type"
ou qu’il n’y a pas depackage.json
dans un dossier parent ; sauf si le fichier contient une syntaxe qui génère des erreurs à moins qu’il ne soit évalué comme un module ES. Les auteurs de packages doivent inclure le champ"type"
, même dans les packages où toutes les sources sont CommonJS. Être explicite sur le type du package facilitera la tâche des outils de construction et des chargeurs pour déterminer comment les fichiers du package doivent être interprétés. - Les fichiers avec une extension autre que
.mjs
,.cjs
,.json
,.node
ou.js
(lorsque le fichierpackage.json
parent le plus proche contient un champ de niveau supérieur"type"
avec la valeur"module"
, ces fichiers ne seront reconnus comme des modules CommonJS que s’ils sont inclus viarequire()
, pas lorsqu’ils sont utilisés comme point d’entrée en ligne de commande du programme).
Voir Détermination du système de modules pour plus de détails.
L’appel de require()
utilise toujours le chargeur de modules CommonJS. L’appel de import()
utilise toujours le chargeur de modules ECMAScript.
Accéder au module principal
Lorsqu'un fichier est exécuté directement depuis 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
, cela sera true
s'il est exécuté via node foo.js
, mais false
s'il est exécuté par require('./foo')
.
Lorsque le point d'entrée n'est pas un module CommonJS, require.main
est undefined
, et le module principal est inaccessible.
Conseils pour les gestionnaires de paquets
La sémantique de la fonction require()
de Node.js a été conçue pour être suffisamment générale pour prendre en charge des structures de répertoires raisonnables. Les programmes de gestion de paquets tels que dpkg
, rpm
et npm
devraient pouvoir créer des paquets natifs à partir de modules Node.js sans modification.
Dans ce qui suit, nous donnons une structure de répertoire suggérée qui pourrait fonctionner :
Supposons que nous voulions que le dossier /usr/lib/node/\<some-package\>/\<some-version\>
contienne le contenu d'une version spécifique d'un paquet.
Les paquets peuvent dépendre les uns des autres. Pour installer le paquet foo
, il peut être nécessaire d'installer une version spécifique du paquet bar
. Le paquet bar
peut lui-même avoir des dépendances, et dans certains cas, celles-ci peuvent même entrer en conflit ou former des dépendances cycliques.
Comme Node.js recherche le realpath
de tous les modules qu'il charge (c'est-à-dire qu'il résout les liens symboliques) puis recherche leurs dépendances dans les dossiers node_modules
, cette situation peut être résolue avec l'architecture suivante :
/usr/lib/node/foo/1.2.3/
: Contenu du paquetfoo
, version 1.2.3./usr/lib/node/bar/4.3.2/
: Contenu du paquetbar
dont dépendfoo
./usr/lib/node/foo/1.2.3/node_modules/bar
: Lien symbolique vers/usr/lib/node/bar/4.3.2/
./usr/lib/node/bar/4.3.2/node_modules/*
: Liens symboliques vers les paquets dont dépendbar
.
Ainsi, même si un cycle est rencontré, ou s'il y a des conflits de dépendances, chaque module sera capable d'obtenir une version de sa dépendance qu'il peut utiliser.
Lorsque le code du paquet foo
effectue require('bar')
, il obtient la version qui est liée symboliquement dans /usr/lib/node/foo/1.2.3/node_modules/bar
. Ensuite, lorsque le code du paquet bar
appelle require('quux')
, il obtient la version qui est liée symboliquement dans /usr/lib/node/bar/4.3.2/node_modules/quux
.
De plus, pour rendre le processus de recherche de module encore plus optimal, plutôt que de placer les paquets directement dans /usr/lib/node
, nous pourrions les placer dans /usr/lib/node_modules/\<name\>/\<version\>
. Node.js ne se donnera alors pas la peine de rechercher les dépendances manquantes dans /usr/node_modules
ou /node_modules
.
Afin de rendre les modules disponibles pour l'interpréteur de commandes Node.js, il pourrait être utile d'ajouter également le dossier /usr/lib/node_modules
à la variable d'environnement $NODE_PATH
. Comme les recherches de modules utilisant les dossiers node_modules
sont toutes relatives et basées sur le chemin réel des fichiers effectuant les appels à require()
, les paquets eux-mêmes peuvent se trouver n'importe où.
Chargement des modules ECMAScript à l'aide de require()
[Historique]
Version | Modifications |
---|---|
v23.5.0 | Cette fonctionnalité n'émet plus d'avertissement expérimental par défaut, bien que l'avertissement puisse toujours être émis par --trace-require-module . |
v23.0.0 | Cette fonctionnalité n'est plus derrière l'indicateur CLI --experimental-require-module . |
v23.0.0 | Prise en charge de l'exportation interop 'module.exports' dans require(esm) . |
v22.0.0, v20.17.0 | Ajouté dans : v22.0.0, v20.17.0 |
[Stable : 1 - Expérimental]
Stable : 1 Stabilité : 1.2 - Candidat à la sortie
L'extension .mjs
est réservée aux modules ECMAScript. Consultez la section Détermination du système de modules pour plus d'informations sur les fichiers analysés en tant que modules ECMAScript.
require()
ne prend en charge que le chargement des modules ECMAScript répondant aux exigences suivantes :
- Le module est entièrement synchrone (ne contient aucun
await
de niveau supérieur) ; et - L'une de ces conditions est remplie :
Si le module ES chargé répond aux exigences, require()
peut le charger et renvoyer l'objet d'espace de noms du module. Dans ce cas, il est similaire à import()
dynamique, mais s'exécute de manière synchrone et renvoie directement l'objet d'espace de noms.
Avec les modules ES suivants :
// distance.mjs
export function distance(a, b) {
return (b.x - a.x) ** 2 + (b.y - a.y) ** 2
}
// point.mjs
export default class Point {
constructor(x, y) {
this.x = x
this.y = y
}
}
Un module CommonJS peut les charger avec require()
:
const distance = require('./distance.mjs')
console.log(distance)
// [Module: null prototype] {
// distance: [Function: distance]
// }
const point = require('./point.mjs')
console.log(point)
// [Module: null prototype] {
// default: [class Point],
// __esModule: true,
// }
Pour l'interopérabilité avec les outils existants qui convertissent les modules ES en CommonJS, qui pourraient ensuite charger de vrais modules ES via require()
, l'espace de noms renvoyé contiendrait une propriété __esModule: true
s'il possède une exportation default
afin que le code consommateur généré par les outils puisse reconnaître les exportations par défaut dans les vrais modules ES. Si l'espace de noms définit déjà __esModule
, celui-ci ne sera pas ajouté. Cette propriété est expérimentale et peut changer à l'avenir. Elle ne doit être utilisée que par les outils convertissant les modules ES en modules CommonJS, suivant les conventions existantes de l'écosystème. Le code écrit directement en CommonJS doit éviter d'en dépendre.
Lorsqu'un module ES contient des exportations nommées et une exportation par défaut, le résultat renvoyé par require()
est l'objet d'espace de noms du module, qui place l'exportation par défaut dans la propriété .default
, de manière similaire aux résultats renvoyés par import()
. Pour personnaliser ce qui doit être renvoyé directement par require(esm)
, le module ES peut exporter la valeur souhaitée en utilisant le nom de chaîne "module.exports"
.
// point.mjs
export default class Point {
constructor(x, y) {
this.x = x
this.y = y
}
}
// `distance` est perdue pour les consommateurs CommonJS de ce module, sauf si elle est
// ajoutée à `Point` en tant que propriété statique.
export function distance(a, b) {
return (b.x - a.x) ** 2 + (b.y - a.y) ** 2
}
export { Point as 'module.exports' }
const Point = require('./point.mjs')
console.log(Point) // [class Point]
// Les exportations nommées sont perdues lorsque 'module.exports' est utilisé
const { distance } = require('./point.mjs')
console.log(distance) // undefined
Notez que dans l'exemple ci-dessus, lorsque le nom d'exportation module.exports
est utilisé, les exportations nommées seront perdues pour les consommateurs CommonJS. Pour permettre aux consommateurs CommonJS de continuer à accéder aux exportations nommées, le module peut s'assurer que l'exportation par défaut est un objet auquel les exportations nommées sont attachées en tant que propriétés. Par exemple, avec l'exemple ci-dessus, distance
peut être attachée à l'exportation par défaut, la classe Point
, en tant que méthode statique.
export function distance(a, b) {
return (b.x - a.x) ** 2 + (b.y - a.y) ** 2
}
export default class Point {
constructor(x, y) {
this.x = x
this.y = y
}
static distance = distance
}
export { Point as 'module.exports' }
const Point = require('./point.mjs')
console.log(Point) // [class Point]
const { distance } = require('./point.mjs')
console.log(distance) // [Function: distance]
Si le module require()
contient un await
de niveau supérieur, ou si le graphe de modules qu'il import
contient un await
de niveau supérieur, ERR_REQUIRE_ASYNC_MODULE
sera levée. Dans ce cas, les utilisateurs doivent charger le module asynchrone à l'aide de import()
.
Si --experimental-print-required-tla
est activé, au lieu de lever ERR_REQUIRE_ASYNC_MODULE
avant l'évaluation, Node.js évaluera le module, tentera de localiser les attentes de niveau supérieur et affichera leur emplacement pour aider les utilisateurs à les corriger.
La prise en charge du chargement des modules ES à l'aide de require()
est actuellement expérimentale et peut être désactivée à l'aide de --no-experimental-require-module
. Pour afficher l'emplacement d'utilisation de cette fonctionnalité, utilisez --trace-require-module
.
Cette fonctionnalité peut être détectée en vérifiant si process.features.require_module
est true
.
Tous ensemble
Pour obtenir le nom de fichier exact qui sera chargé lors de l'appel de require()
, utilisez la fonction require.resolve()
.
En rassemblant tout ce qui précède, voici l'algorithme de haut niveau en pseudo-code de ce que fait require()
:
require(X) depuis le module au chemin Y
1. Si X est un module principal,
a. renvoyer le module principal
b. STOP
2. Si X commence par '/'
a. définir Y comme étant la racine du système de fichiers
3. Si X commence par './' ou '/' ou '../'
a. LOAD_AS_FILE(Y + X)
b. LOAD_AS_DIRECTORY(Y + X)
c. LANCER "non trouvé"
4. Si X commence par '#'
a. LOAD_PACKAGE_IMPORTS(X, dirname(Y))
5. LOAD_PACKAGE_SELF(X, dirname(Y))
6. LOAD_NODE_MODULES(X, dirname(Y))
7. LANCER "non trouvé"
MAYBE_DETECT_AND_LOAD(X)
1. Si X est analysé comme un module CommonJS, charger X comme un module CommonJS. STOP.
2. Sinon, si le code source de X peut être analysé comme un module ECMAScript en utilisant
<a href="esm#resolver-algorithm-specification">DETECT_MODULE_SYNTAX défini dans
le solveur ESM</a>,
a. Charger X comme un module ECMAScript. STOP.
3. LANCER l'erreur SyntaxError résultant de la tentative d'analyse de X comme CommonJS en 1. STOP.
LOAD_AS_FILE(X)
1. Si X est un fichier, charger X selon le format de son extension. STOP
2. Si X.js est un fichier,
a. Trouver la portée de package SCOPE la plus proche de X.
b. Si aucune portée n'a été trouvée
1. MAYBE_DETECT_AND_LOAD(X.js)
c. Si le champ SCOPE/package.json contient le champ "type",
1. Si le champ "type" est "module", charger X.js comme un module ECMAScript. STOP.
2. Si le champ "type" est "commonjs", charger X.js comme un module CommonJS. STOP.
d. MAYBE_DETECT_AND_LOAD(X.js)
3. Si X.json est un fichier, charger X.json en tant qu'objet JavaScript. STOP
4. Si X.node est un fichier, charger X.node comme extension binaire. STOP
LOAD_INDEX(X)
1. Si X/index.js est un fichier
a. Trouver la portée de package SCOPE la plus proche de X.
b. Si aucune portée n'a été trouvée, charger X/index.js comme un module CommonJS. STOP.
c. Si le champ SCOPE/package.json contient le champ "type",
1. Si le champ "type" est "module", charger X/index.js comme un module ECMAScript. STOP.
2. Sinon, charger X/index.js comme un module CommonJS. STOP.
2. Si X/index.json est un fichier, analyser X/index.json en un objet JavaScript. STOP
3. Si X/index.node est un fichier, charger X/index.node comme extension binaire. STOP
LOAD_AS_DIRECTORY(X)
1. Si X/package.json est un fichier,
a. Analyser X/package.json, et rechercher le champ "main".
b. Si "main" est une valeur fausse, aller en 2.
c. soit M = X + (champ principal json)
d. LOAD_AS_FILE(M)
e. LOAD_INDEX(M)
f. LOAD_INDEX(X) DÉPRECIE
g. LANCER "non trouvé"
2. LOAD_INDEX(X)
LOAD_NODE_MODULES(X, START)
1. soit DIRS = NODE_MODULES_PATHS(START)
2. pour chaque DIR dans DIRS :
a. LOAD_PACKAGE_EXPORTS(X, DIR)
b. LOAD_AS_FILE(DIR/X)
c. LOAD_AS_DIRECTORY(DIR/X)
NODE_MODULES_PATHS(START)
1. soit PARTS = division de chemin(START)
2. soit I = nombre de PARTS - 1
3. soit DIRS = []
4. tant que I >= 0,
a. si PARTS[I] = "node_modules", aller en d.
b. DIR = joindre chemin(PARTS[0 .. I] + "node_modules")
c. DIRS = DIR + DIRS
d. soit I = I - 1
5. renvoyer DIRS + GLOBAL_FOLDERS
LOAD_PACKAGE_IMPORTS(X, DIR)
1. Trouver la portée de package SCOPE la plus proche de DIR.
2. Si aucune portée n'a été trouvée, renvoyer.
3. Si SCOPE/package.json "imports" est nul ou indéfini, renvoyer.
4. Si `--experimental-require-module` est activé
a. soit CONDITIONS = ["node", "require", "module-sync"]
b. Sinon, soit CONDITIONS = ["node", "require"]
5. soit MATCH = PACKAGE_IMPORTS_RESOLVE(X, pathToFileURL(SCOPE),
CONDITIONS) <a href="esm#resolver-algorithm-specification">défini dans le solveur ESM</a>.
6. RESOLVE_ESM_MATCH(MATCH).
LOAD_PACKAGE_EXPORTS(X, DIR)
1. Essayer d'interpréter X comme une combinaison de NAME et SUBPATH où le nom
peut avoir un préfixe @scope/ et le sous-chemin commence par une barre oblique (`/`).
2. Si X ne correspond pas à ce modèle ou si DIR/NAME/package.json n'est pas un fichier,
renvoyer.
3. Analyser DIR/NAME/package.json, et rechercher le champ "exports".
4. Si "exports" est nul ou indéfini, renvoyer.
5. Si `--experimental-require-module` est activé
a. soit CONDITIONS = ["node", "require", "module-sync"]
b. Sinon, soit CONDITIONS = ["node", "require"]
6. soit MATCH = PACKAGE_EXPORTS_RESOLVE(pathToFileURL(DIR/NAME), "." + SUBPATH,
`package.json` "exports", CONDITIONS) <a href="esm#resolver-algorithm-specification">défini dans le solveur ESM</a>.
7. RESOLVE_ESM_MATCH(MATCH)
LOAD_PACKAGE_SELF(X, DIR)
1. Trouver la portée de package SCOPE la plus proche de DIR.
2. Si aucune portée n'a été trouvée, renvoyer.
3. Si SCOPE/package.json "exports" est nul ou indéfini, renvoyer.
4. Si SCOPE/package.json "name" n'est pas le premier segment de X, renvoyer.
5. soit MATCH = PACKAGE_EXPORTS_RESOLVE(pathToFileURL(SCOPE),
"." + X.slice("name".length), `package.json` "exports", ["node", "require"])
<a href="esm#resolver-algorithm-specification">défini dans le solveur ESM</a>.
6. RESOLVE_ESM_MATCH(MATCH)
RESOLVE_ESM_MATCH(MATCH)
1. soit RESOLVED_PATH = fileURLToPath(MATCH)
2. Si le fichier à RESOLVED_PATH existe, charger RESOLVED_PATH selon le format de son extension. STOP
3. LANCER "non trouvé"
Mise en cache
Les modules sont mis en cache après leur premier chargement. Cela signifie (entre autres) que chaque appel à require('foo')
retournera exactement le même objet s'il est résolu vers le même fichier.
À condition que require.cache
ne soit pas modifié, plusieurs appels à require('foo')
n'entraîneront pas l'exécution multiple du code du module. C'est une fonctionnalité importante. Grâce à cela, des objets « partiellement terminés » peuvent être retournés, permettant ainsi le chargement des dépendances transitives même lorsqu'elles provoquent 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 du nom de fichier résolu. Étant donné que les modules peuvent être résolus vers un nom de fichier différent en fonction de l'emplacement du module appelant (chargement à partir des dossiers node_modules
), il n'est pas garanti que require('foo')
retournera toujours exactement le même objet s'il est résolu vers des fichiers différents.
De plus, sur les systèmes de fichiers ou les systèmes d'exploitation ne respectant pas 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')
et require('./FOO')
retournent deux objets différents, indépendamment du fait que ./foo
et ./FOO
soient ou non le même fichier.
Modules intégrés
[Historique]
Version | Modifications |
---|---|
v16.0.0, v14.18.0 | Ajout de la prise en charge de l'importation node: à require(...) . |
Node.js possède plusieurs modules compilés dans le binaire. Ces modules sont décrits plus en détail ailleurs dans cette documentation.
Les modules intégrés sont définis dans la source Node.js et se trouvent dans le dossier lib/
.
Les modules intégrés peuvent être identifiés à l'aide du préfixe node:
, auquel cas il contourne le cache require
. Par exemple, require('node:http')
retournera toujours le module HTTP intégré, même s'il existe une entrée require.cache
de ce nom.
Certains modules intégrés sont toujours chargés de préférence si leur identificateur est passé à require()
. Par exemple, require('http')
retournera toujours le module HTTP intégré, même s'il existe un fichier de ce nom. La liste des modules intégrés pouvant être chargés sans utiliser le préfixe node:
est exposée dans module.builtinModules
, listés sans le préfixe.
Modules intégrés avec préfixe node:
obligatoire
Lorsqu'ils sont chargés par require()
, certains modules intégrés doivent être demandés avec le préfixe node:
. Cette exigence existe pour empêcher les nouveaux modules intégrés d'entrer en conflit avec les paquets de l'espace utilisateur qui ont déjà pris le nom. Actuellement, les modules intégrés qui nécessitent le préfixe node:
sont :
La liste de ces modules est exposée dans module.builtinModules
, y compris le préfixe.
Cycles
Lorsqu'il y a des appels require()
circulaires, un module peut ne pas avoir fini de s'exécuter lorsqu'il est renvoyé.
Considérez cette situation :
a.js
:
console.log('a starting')
exports.done = false
const b = require('./b.js')
console.log('in a, b.done = %j', b.done)
exports.done = true
console.log('a done')
b.js
:
console.log('b starting')
exports.done = false
const a = require('./a.js')
console.log('in b, a.done = %j', a.done)
exports.done = true
console.log('b done')
main.js
:
console.log('main starting')
const a = require('./a.js')
const b = require('./b.js')
console.log('in main, a.done = %j, b.done = %j', a.done, b.done)
Lorsque main.js
charge a.js
, puis a.js
charge à son tour b.js
. À ce moment-là, b.js
essaie de charger a.js
. Afin d'éviter une boucle infinie, une copie incomplète de l'objet exports
de a.js
est renvoyée au module b.js
. b.js
termine ensuite le chargement, et son objet exports
est fourni au module a.js
.
Au moment où main.js
a chargé les deux modules, ils sont tous les deux terminés. La sortie de ce programme serait donc :
$ node main.js
main starting
a starting
b starting
in b, a.done = false
b done
in a, b.done = true
a done
in main, a.done = true, b.done = true
Une planification minutieuse est nécessaire pour permettre aux dépendances de modules cycliques de fonctionner correctement au sein d'une application.
Modules de fichiers
Si le nom de fichier exact n'est pas trouvé, 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 ayant 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')
).
Les fichiers .json
sont analysés comme des fichiers texte JSON, les fichiers .node
sont interprétés comme des modules d'extension compilés chargés avec process.dlopen()
. Les fichiers utilisant une autre extension (ou aucune extension) sont analysés comme des fichiers texte JavaScript. Reportez-vous à la section Détermination du système de modules pour comprendre quel objectif d'analyse sera utilisé.
Un module requis préfixé par /
est un chemin absolu vers le fichier. Par exemple, require('/home/marco/foo.js')
chargera le fichier situé à /home/marco/foo.js
.
Un module requis préfixé par './'
est relatif au fichier appelant require()
. C'est-à-dire que circle.js
doit se trouver dans le même répertoire que foo.js
pour que require('./circle')
le trouve.
Sans un préfixe /
, './'
ou '../'
pour indiquer un fichier, le module doit être soit un module principal, soit chargé à partir d'un dossier node_modules
.
Si le chemin donné n'existe pas, require()
lèvera une erreur MODULE_NOT_FOUND
.
Dossiers comme modules
[Stable : 3 - Hérité]
Stable : 3 Stabilité : 3 - Hérité : Utilisez plutôt les exportations de sous-chemins ou les importations de sous-chemins.
Il existe trois manières dont un dossier peut être passé à require()
comme argument.
La première consiste à créer un fichier package.json
à la racine du dossier, qui spécifie un module main
. Un exemple de fichier package.json
pourrait ressembler à ceci :
{ "name": "some-library", "main": "./lib/some-library.js" }
Si cela se trouvait dans un dossier à ./some-library
, alors require('./some-library')
tenterait de charger ./some-library/lib/some-library.js
.
S'il n'y a pas de fichier package.json
présent dans le répertoire, ou si l'entrée "main"
est manquante ou ne peut pas être résolue, alors Node.js tentera de charger un fichier index.js
ou index.node
à partir de ce répertoire. Par exemple, s'il n'y avait pas de fichier package.json
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 que le module entier est manquant avec l'erreur par défaut :
Error: Cannot find module 'some-library'
Dans les trois cas ci-dessus, un appel import('./some-library')
entraînerait une erreur ERR_UNSUPPORTED_DIR_IMPORT
. L'utilisation des exportations de sous-chemins ou des importations de sous-chemins des packages peut fournir les mêmes avantages d'organisation du confinement que les dossiers en tant que modules, et fonctionner pour require
et import
.
Chargement depuis les dossiers node_modules
Si l'identificateur de module passé à require()
n'est pas un module intégré, et ne commence pas par '/'
, '../'
, ou './'
, alors Node.js commence par le répertoire du module courant, ajoute /node_modules
, et tente de charger le module depuis cet emplacement. Node.js n'ajoutera pas node_modules
à un chemin se terminant déjà par node_modules
.
S'il n'est pas trouvé là, alors 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 situé à '/home/ry/projects/foo.js'
appelle require('bar.js')
, alors Node.js recherchera aux 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 ne soient pas en conflit.
Il est possible de requérir 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'emplacement de example-module
. Le chemin suffixé suit la même sémantique de résolution de module.
Chargement depuis les dossiers globaux
Si la variable d'environnement NODE_PATH
est définie sur une liste de chemins absolus séparés par des deux-points, alors Node.js recherchera ces chemins pour les modules s'ils ne sont pas trouvés ailleurs.
Sous Windows, NODE_PATH
est délimité par des points-virgules (;
) au lieu de deux-points.
NODE_PATH
a été initialement créé pour prendre en charge le chargement de modules à partir de chemins variés avant que l'algorithme actuel de résolution de module ne soit défini.
NODE_PATH
est toujours pris en charge, mais est moins nécessaire maintenant que l'écosystème Node.js s'est stabilisé sur une convention pour localiser les modules dépendants. Parfois, les déploiements qui reposent sur NODE_PATH
présentent un comportement surprenant lorsque les personnes ignorent que NODE_PATH
doit être défini. Parfois, les dépendances d'un module changent, ce qui provoque le chargement d'une version différente (ou même d'un module différent) lors de la recherche de NODE_PATH
.
De plus, Node.js recherchera dans la liste suivante de DOSSIERS_GLOBAUX :
- 1:
$HOME/.node_modules
- 2:
$HOME/.node_libraries
- 3:
$PREFIX/lib/node
Où $HOME
est le répertoire personnel de l'utilisateur, et $PREFIX
est le node_prefix
configuré par Node.js.
Ceci est principalement dû à des raisons historiques.
Il est fortement recommandé de placer les dépendances dans le dossier node_modules
local. Celles-ci seront chargées plus rapidement et de manière plus fiable.
L'enveloppe du module
Avant l'exécution du code d'un module, Node.js l'enveloppe dans une fonction qui ressemble à ceci :
;(function (exports, require, module, __filename, __dirname) {
// Le code du module se trouve ici
})
En procédant ainsi, Node.js accomplit plusieurs choses :
- Il maintient les variables de niveau supérieur (définies avec
var
,const
oulet
) dans l'étendue du module plutôt que dans l'objet global. - Il permet de fournir des variables ayant une apparence globale mais qui sont en réalité spécifiques au module, telles que :
- Les objets
module
etexports
que l'implémenteur peut utiliser pour exporter des valeurs depuis le module. - Les variables de commodité
__filename
et__dirname
, contenant respectivement le nom de fichier absolu et le chemin d'accès au répertoire du module.
- Les objets
L'étendue du module
__dirname
Ajouté dans : v0.1.27
Le nom du répertoire du module courant. Il s'agit de la même chose que path.dirname()
de __filename
.
Exemple : exécution de node example.js
depuis /Users/mjr
console.log(__dirname)
// Affiche : /Users/mjr
console.log(path.dirname(__filename))
// Affiche : /Users/mjr
__filename
Ajouté dans : v0.0.1
Le nom de fichier du module courant. Il s'agit du chemin absolu du fichier du module courant, avec les liens symboliques résolus.
Pour un programme principal, ce n'est pas forcément le même que le nom de fichier utilisé dans la ligne de commande.
Voir __dirname
pour le nom du répertoire du module courant.
Exemples :
Exécution de node example.js
depuis /Users/mjr
console.log(__filename)
// Affiche : /Users/mjr/example.js
console.log(__dirname)
// Affiche : /Users/mjr
Étant donné deux modules : a
et b
, où b
est une dépendance de a
et il existe une structure de répertoires :
/Users/mjr/app/a.js
/Users/mjr/app/node_modules/b/b.js
Les références à __filename
dans b.js
renverront /Users/mjr/app/node_modules/b/b.js
tandis que les références à __filename
dans a.js
renverront /Users/mjr/app/a.js
.
exports
Ajouté dans : v0.1.12
Une référence à module.exports
plus courte à taper. Consultez la section sur le raccourci exports pour plus de détails sur quand utiliser exports
et quand utiliser module.exports
.
module
Ajouté dans : v0.1.16
Une référence au module courant, consultez la section sur l'objet module
. En particulier, module.exports
est utilisé pour définir ce qu'un module exporte et met à disposition via require()
.
require(id)
Ajouté dans : v0.1.13
id
<chaîne de caractères> nom ou chemin du module- Retourne : <quelconque> contenu du module exporté
Utilisé pour importer des modules, JSON
et des fichiers locaux. Les modules peuvent être importés depuis node_modules
. Les modules locaux et les fichiers JSON peuvent être importés en utilisant un chemin relatif (par exemple : ./
, ./foo
, ./bar/baz
, ../foo
) qui sera résolu par rapport au répertoire nommé par __dirname
(s'il est défini) ou le répertoire de travail courant. Les chemins relatifs de 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 que sous les systèmes Unix.
// Importation d'un module local avec un chemin relatif à `__dirname` ou au répertoire de travail courant. (Sous Windows, cela correspondrait à .\path\myLocalModule.)
const myLocalModule = require('./path/myLocalModule')
// Importation d'un fichier JSON :
const jsonData = require('./path/filename.json')
// Importation d'un module depuis node_modules ou un module intégré Node.js :
const crypto = require('node:crypto')
require.cache
Ajouté dans : v0.3.0
Les modules sont mis en cache dans cet objet lorsqu'ils sont requis. En supprimant une paire clé-valeur de cet objet, le prochain require
rechargera le module. Cela ne s'applique pas aux modules natifs, pour lesquels un rechargement entraînera une erreur.
L'ajout ou le remplacement d'entrées est également possible. Ce cache est vérifié avant les modules intégrés et si un nom correspondant à un module intégré est ajouté au cache, seules les appels require
préfixés par node:
vont recevoir le module intégré. À utiliser avec précaution !
const assert = require('node:assert')
const realFs = require('node:fs')
const fakeFs = {}
require.cache.fs = { exports: fakeFs }
assert.strictEqual(require('fs'), fakeFs)
assert.strictEqual(require('node:fs'), realFs)
require.extensions
Ajouté dans : v0.3.0
Déprécié depuis : v0.10.6
[Stable : 0 - Déprécié]
Stable : 0 Stabilité : 0 - Déprécié
Instruit require
sur la façon de gérer certaines extensions de fichiers.
Traiter les fichiers avec l'extension .sjs
comme .js
:
require.extensions['.sjs'] = require.extensions['.js']
Déprécié. Par le passé, cette liste a été utilisée pour charger des modules non JavaScript dans Node.js en les compilant à la demande. Cependant, en pratique, il existe de bien meilleures façons de procéder, telles que le chargement de modules via un autre programme Node.js ou leur compilation en JavaScript à l'avance.
Évitez d'utiliser require.extensions
. Son utilisation peut entraîner des bogues subtils et la résolution des extensions devient plus lente à chaque extension enregistrée.
require.main
Ajouté dans : v0.1.17
L'objet Module
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ès au module principal".
Dans le script entry.js
:
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' ] }
require.resolve(request[, options])
[Historique]
Version | Modifications |
---|---|
v8.9.0 | L'option paths est désormais prise en charge. |
v0.3.0 | Ajouté dans : v0.3.0 |
request
<chaîne de caractères> Le chemin du module à résoudre.options
<Objet>paths
<tableau de chaînes de caractères> Chemins pour résoudre l'emplacement du module à partir de. Si présents, ces chemins sont utilisés à la place des chemins de résolution par défaut, à l'exception des DOSSIERS_GLOBALS comme$HOME/.node_modules
, qui sont toujours inclus. Chacun de ces chemins est utilisé comme point de départ pour l'algorithme de résolution de module, ce qui signifie que la hiérarchienode_modules
est vérifiée à partir de cet emplacement.
Retourne : <chaîne de caractères>
Utilisez le mécanisme interne require()
pour rechercher l'emplacement d'un module, mais au lieu de charger le module, retournez simplement le nom de fichier résolu.
Si le module est introuvable, une erreur MODULE_NOT_FOUND
est levée.
require.resolve.paths(request)
Ajouté dans : v8.9.0
request
<string> Le chemin du module dont les chemins de recherche sont récupérés.- Retourne : <string[]> | <null>
Retourne un tableau contenant les chemins parcourus lors de la résolution de request
ou null
si la chaîne request
fait référence à un module principal, par exemple http
ou fs
.
L'objet module
Ajouté dans : v0.1.16
Dans chaque module, la variable libre module
est une référence à l'objet représentant le module courant. Pour plus de commodité, module.exports
est également accessible via le module global exports
. module
n'est pas réellement un global, mais plutôt local à chaque module.
module.children
Ajouté dans : v0.1.16
Les objets module requis pour la première fois par celui-ci.
module.exports
Ajouté dans : v0.1.16
L'objet module.exports
est créé par le système Module
. Parfois, ce n'est pas acceptable ; beaucoup veulent que leur module soit une instance d'une certaine classe. Pour ce faire, affectez l'objet d'exportation souhaité à module.exports
. L'affectation de l'objet souhaité à exports
se contentera de relire la variable locale exports
, ce qui n'est probablement pas ce qui est souhaité.
Par exemple, supposons que nous créions un module appelé a.js
:
const EventEmitter = require('node:events')
module.exports = new EventEmitter()
// Effectuez un certain travail, et après un certain temps, émettez
// l'événement 'ready' depuis le module lui-même.
setTimeout(() => {
module.exports.emit('ready')
}, 1000)
Ensuite, dans un autre fichier, nous pourrions faire :
const a = require('./a')
a.on('ready', () => {
console.log('le module "a" est prêt')
})
L'affectation à module.exports
doit ê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)
Raccourci exports
Ajouté dans : v0.1.16
La variable exports
est disponible dans la portée de niveau fichier d’un module et se voit assigner la valeur de module.exports
avant l’évaluation du module.
Elle permet un raccourci, de sorte que module.exports.f = ...
puisse s’écrire plus succinctement exports.f = ...
. Cependant, sachez que, comme toute variable, si une nouvelle valeur est assignée à exports
, elle n’est plus liée à module.exports :
module.exports.hello = true // Exporté depuis require du module
exports = { hello: false } // Non exporté, seulement disponible dans le module
Lorsque la propriété module.exports
est complètement remplacée par un nouvel objet, il est courant de réassigner é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) => {
// Code du module ici. Dans cet exemple, définir une fonction.
function someFunc() {}
exports = someFunc
// À ce stade, exports n’est plus un raccourci vers module.exports, et
// ce module exportera toujours un objet par défaut vide.
module.exports = someFunc
// À ce stade, le module exportera maintenant someFunc, au lieu de
// l’objet par défaut.
})(module, module.exports)
return module.exports
}
module.filename
Ajouté dans : v0.1.16
Le nom de fichier entièrement résolu du module.
module.id
Ajouté dans : v0.1.16
L’identifiant du module. Typiquement, il s’agit du nom de fichier entièrement résolu.
module.isPreloading
Ajouté dans : v15.4.0, v14.17.0
- Type : <boolean>
true
si le module s’exécute pendant la phase de préchargement Node.js.
module.loaded
Ajouté dans : v0.1.16
Indique si le module a fini de se charger ou est en cours de chargement.
module.parent
Ajouté dans : v0.1.16
Déprécié depuis : v14.6.0, v12.19.0
[Stable : 0 - Déprécié]
Stable : 0 Stabilité : 0 - Déprécié : Veuillez utiliser require.main
et module.children
à la place.
- <module> | <null> | <indéfini>
Le module qui a d'abord requis celui-ci, ou null
si le module courant est le point d'entrée du processus courant, ou undefined
si le module a été chargé par quelque chose qui n'est pas un module CommonJS (par exemple : REPL ou import
).
module.path
Ajouté dans : v11.14.0
Le nom du répertoire du module. Ceci est généralement identique à path.dirname()
de module.id
.
module.paths
Ajouté dans : v0.4.0
Les chemins de recherche pour le module.
module.require(id)
Ajouté dans : v0.5.1
id
<chaîne de caractères>- Retourne : <n'importe quoi> contenu du module exporté
La méthode module.require()
fournit un moyen de charger un module comme si require()
avait été appelé depuis le module d'origine.
Pour ce faire, il est nécessaire d'obtenir une référence à l'objet module
. Puisque require()
retourne module.exports
, et que le module
est généralement uniquement disponible dans le code d'un module spécifique, il doit être explicitement exporté pour pouvoir être utilisé.
L'objet Module
Cette section a été déplacée vers Modules : module principal module
.
Prise en charge de Source map v3
Cette section a été déplacée vers Modules : module principal module
.