Nel Nodo.sistema di moduli js, ogni file viene trattato come un modulo separato. Ad esempio, si consideri un file chiamato foo.js
:
const circle = require('./circle.js');console.log(`The area of a circle of radius 4 is ${circle.area(4)}`);
Nella prima riga foo.js
carica il modulo circle.js
che è in samedirectory come foo.js
.,
di seguito il contenuto di circle.js
:
const { PI } = Math;exports.area = (r) => PI * r ** 2;exports.circumference = (r) => 2 * PI * r;
modulo circle.js
ha esportato le funzioni area()
ecircumference()
. Funzioni e oggetti vengono aggiunti alla radice di un modulo specificando proprietà aggiuntive sullo specialeexports
oggetto.
Le variabili locali al modulo saranno private, perché il modulo è avvolto in una funzione per Nodo.js (vedere modulo wrapper). In questo esempio, la variabile PI
è privata a circle.js
.,
Alla proprietà module.exports
può essere assegnato un nuovo valore (ad esempio un oggetto functionor).
di Seguito, bar.js
fa uso del tag square
modulo, che esporta in un Quadrato di classe:
const Square = require('./square.js');const mySquare = new Square(2);console.log(`The area of mySquare is ${mySquare.area()}`);
square
modulo è definito in square.js
:
Il modulo di sistema è implementato nel require('module')
modulo.
Accesso al modulo principale #
Quando un file viene eseguito direttamente dal nodo.js, require.main
è impostato sul suomodule
., Ciò significa che è possibile determinare se un file è stato eseguito direttamente testando require.main === module
.
Per un file foo.js
, questo sarà true
se eseguito tramite node foo.js
, mafalse
se eseguito con require('./foo')
.
Poiché module
fornisce una proprietàfilename
(normalmente equivalente a __filename
), è possibile ottenere il punto di ingresso dell’applicazione corrente controllando require.main.filename
.,
Addenda: Package manager tips#
La semantica del Nodo.jsrequire()
funzione sono stati progettati per essere generalenough per supportare strutture di directory ragionevoli. Programmi di gestione dei pacchetti come dpkg
, rpm
e npm
si spera che sia possibile costruire pacchetti nativi dal Nodo.moduli js senza modifiche.
Di seguito diamo una struttura di directory suggerita che potrebbe funzionare:
I pacchetti possono dipendere l’uno dall’altro., Per installare il pacchetto foo
, può essere necessario installare una versione specifica del pacchetto bar
. Il pacchettobar
può avere dipendenze e, in alcuni casi, queste possono persino scontrarsi o formare dipendenze cicliche.
Perché Nodo.,js cerca il realpath
qualsiasi dei moduli caricati (che è, itresolves link simbolici) e poi si guarda per loro dipendenze nel node_modules
cartelle,questa situazione può essere risolta con la seguente architettura:
Così, anche se un ciclo è verificato, o se ci sono dependencyconflicts, ogni modulo sarà in grado di ottenere una versione del suo dependencythat è possibile utilizzare.
Per rendere disponibili i moduli al Nodo.js REPL, potrebbe essere utile aggiungere anche la cartella/usr/lib/node_modules
alla cartella$NODE_PATH
environmentvariable., Poiché le ricerche del modulo utilizzando le cartellenode_modules
sono allrelative e basate sul percorso reale dei file che effettuano le chiamate arequire()
, i pacchetti stessi possono essere ovunque.
Addenda: Il .estensione mjs#
Non è possibilerequire()
file con estensione.mjs
.Il tentativo di farlo genererà un errore. L’estensione.mjs
è riservata ai moduli ECMAScript che non possono essere caricati tramiterequire()
.Vedere Moduli ECMAScript per maggiori dettagli.,
Tutti insieme…#
Per ottenere il nome file esatto che verrà caricato quando viene chiamato require()
, usala funzione require.resolve()
.
Mettendo insieme tutto quanto sopra, ecco lo pseudocodice algoritmico di alto livello di ciò che farequire()
:
Caching#
I moduli vengono memorizzati nella cache dopo la prima volta che vengono caricati. Ciò significa (tra le altre cose) che ogni chiamata a require('foo')
otterrà esattamente lo stesso objectreturned, se si risolverà nello stesso file.,
Fornito require.cache
non viene modificato, più chiamate a require('foo')
non causerà l’esecuzione del codice del modulo più volte. Questa è una caratteristica importante. Con esso, gli oggetti” parzialmente fatti ” possono essere restituiti, consentendo quindi di caricare le dipendenze transitive anche quando causerebbero cicli.
Per avere un modulo eseguire il codice più volte, esportare una funzione e chiamare thatfunction.
Avvertenze per la memorizzazione nella cache dei moduli#
I moduli vengono memorizzati nella cache in base al nome del file risolto., Poiché i moduli possono risolvere un nome di file diverso in base alla posizione del modulo chiamante (loadingfrom node_modules
cartelle), non è una garanzia che require('foo')
restituirà sempre lo stesso oggetto, se si risolverà in file diversi.
Inoltre, su file system o sistemi operativi senza distinzione tra maiuscole e minuscole, i nomi di file differentresolved possono puntare allo stesso file, ma la cache li tratterà ancora come moduli diversi e ricaricherà il file più volte., Ad esempio,require('./foo')
erequire('./FOO')
restituiscono due oggetti diversi, indipendentemente dal fatto che./foo
e./FOO
siano lo stesso file.
Moduli di base #
Nodo.js ha diversi moduli compilati nel binario. Questi moduli sono descritti più dettagliatamente altrove in questa documentazione.
I moduli principali sono definiti all’interno del Nodo.sorgente js e si trovano nella cartellalib/
.,
I moduli core vengono sempre caricati preferenzialmente se il loro identificatore viene passato arequire()
. Ad esempio, require('http')
restituirà sempre il modulo HTTP integrato, anche se esiste un file con quel nome.
Cicli #
Quando ci sono chiamate circolarirequire()
, un modulo potrebbe non essere stato completato quando viene restituito.,
prendere in Considerazione questa situazione:
a.js
:
b.js
:
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);
Quando main.js
carica a.js
, quindi a.js
carica b.js
. A quel punto,b.js
tenta di caricarea.js
. Per evitare un infiniteloop, una copia incompiuta dell’oggetto di esportazione a.js
viene restituita al modulob.js
., b.js
quindi termina il caricamento e il suo oggettoexports
viene fornito al moduloa.js
.
Quando main.js
ha caricato entrambi i moduli, sono entrambi finiti.L’output di questo programma sarebbe quindi:
$ node main.jsmain startinga startingb startingin b, a.done = falseb donein a, b.done = truea donein main, a.done = true, b.done = true
È necessaria un’attenta pianificazione per consentire alle dipendenze cicliche dei moduli di funzionare correttamente all’interno di un’applicazione.
File modules #
Se il nome file esatto non viene trovato, quindi Nodo.,js tenterà di caricare il nome del file richiesto con le estensioni aggiunte: .js
, .json
, e infine.node
.
.js
i file vengono interpretati come file di testo JavaScript e .json
i file vengono analizzati come file di testo JSON. .node
i file vengono interpretati come moduli aggiuntivi compilati caricati con process.dlopen()
.,
Senza un leading '/'
, './'
, o '../'
per indicare un file, il modulo deve essere un modulo principale o viene caricato da una cartella node_modules
.
Se il percorso specificato non esiste, require()
genererà una proprietà Error
con la sua proprietàcode
impostata su 'MODULE_NOT_FOUND'
.,
Cartelle come moduli#
È conveniente organizzare programmi e librerie in directory autocontenute e quindi fornire un singolo punto di ingresso a tali directory.Ci sono tre modi in cui una cartella può essere passata arequire()
asan argomento.
Il primo consiste nel creare un file package.json
nella radice della cartella,che specifica un modulo main
., Un esempio package.json
il file potrebbe assomigliare a questo:
{ "name" : "some-library", "main" : "./lib/some-library.js" }
Se questo si trovava in una cartella in ./some-library
, allorarequire('./some-library')
tenterebbe di caricare./some-library/lib/some-library.js
.
Questa è l’estensione della consapevolezza dei file package.json
all’interno del Nodo.js.
Se nella directory non è presente alcun file package.json
o se la voce"main"
manca o non può essere risolta, allora Node.,jsotentirà di caricare un fileindex.js
oindex.node
fuori da thatdirectory. Per esempio, se non c’era package.json
file in previousexample, quindi require('./some-library')
avrebbe tentato di carico:
./some-library/index.js
./some-library/index.node
Se questi tentativi, quindi il Nodo.,js segnalerà l’intero modulo come mancantecon l’errore predefinito:
Error: Cannot find module 'some-library'
Caricamento dalle cartelle node_modules#
Se non viene trovato lì, si sposta nella directory principale e presto, fino a raggiungere la radice del file system.
/home/ry/projects/node_modules/bar.js
/home/ry/node_modules/bar.js
/home/node_modules/bar.js
/node_modules/bar.js
Questo permette ai programmi di localizzare le loro dipendenze, in modo che essi non notclash.,
È possibile richiedere file specifici o sotto moduli distribuiti con amodule includendo un suffisso di percorso dopo il nome del modulo. Ad esempiorequire('example-module/path/to/file')
risolverebbepath/to/file
rispetto a dove si trovaexample-module
. Il percorso suffisso segue la stessa semantica della risoluzione del modulo.
Caricamento dalle cartelle globali#
Se la variabile di ambienteNODE_PATH
è impostata su un elenco delimitato da due punti di percorsi assoluti, quindi Nodo.js cercherà quei percorsi per i moduli se non si trovano altrove.,
Su Windows,NODE_PATH
è delimitato da punti e virgola (;
) invece di due punti.
NODE_PATH
è stato originariamente creato per supportare il caricamento di moduli fromvarying paths prima che l’algoritmo di risoluzione del modulo corrente fosse definito.
NODE_PATH
è ancora supportato, ma è meno necessario ora che il Nodo.jsecosystem ha stabilito una convenzione per localizzare i moduli dipendenti.,A volte le distribuzioni che si basano suNODE_PATH
mostrano comportamenti sorprendenti quando le persone non sono consapevoli cheNODE_PATH
deve essere impostato. A volte le dipendenze di amodule cambiano, causando il caricamento di una versione diversa (o anche di un modulo diverso) quando viene cercato NODE_PATH
.
Inoltre, Nodo.,js cerca nel seguente elenco di GLOBAL_FOLDERS:
- 1:
$HOME/.node_modules
- 2:
$HOME/.node_libraries
- 3:
$PREFIX/lib/node
Dove $HOME
è la directory home dell’utente, e $PREFIX
è il Nodo.jsconfigurednode_prefix
.
Questi sono per lo più per ragioni storiche.
Si consiglia vivamente di inserire le dipendenze nella cartella locale node_modules
. Questi saranno caricati più velocemente e in modo più affidabile.,
Il wrapper del modulo#
Prima che il codice di un modulo venga eseguito, Nodo.js lo avvolgerà con un functionwrapper che assomiglia al seguente:
(function(exports, require, module, __filename, __dirname) {// Module code actually lives in here});
Facendo questo, Node.js realizza alcune cose:
- Mantiene le variabili di primo livello (definite con
var
,const
olet
) nell’ambito del modulo piuttosto che dell’oggetto globale., - Aiuta a fornire alcune variabili dall’aspetto globale che sono effettivamente specifiche del modulo, come ad esempio:
- Gli oggetti
module
eexports
che l’implementatore può utilizzare per esportare i valori dal modulo. - Le variabili di convenienza
__filename
e__dirname
, contenenti il nome del file assoluto del modulo e il percorso della directory.
- Gli oggetti
L’ambito del modulo#
_ _ dirname#
- <string>
Il nome della directory del modulo corrente. Questo è lo stesso delpath.dirname()
del __filename
.
Esempio: esecuzione di node example.js
da /Users/mjr
console.log(__dirname);// Prints: /Users/mjrconsole.log(path.dirname(__filename));// Prints: /Users/mjr
__filename#
- <string>
Il nome del file del modulo corrente. Questo è absolutepath del file del modulo corrente con i collegamenti simbolici risolti.,
Per un programma principale questo non è necessariamente lo stesso del nome del file utilizzato nella riga di comando.
Vedere__dirname
per il nome della directory del modulo corrente.,
Examples:
Running node example.js
from /Users/mjr
console.log(__filename);// Prints: /Users/mjr/example.jsconsole.log(__dirname);// Prints: /Users/mjr
Given two modules: a
and b
, where b
is a dependency ofa
and there is a directory structure of:
/Users/mjr/app/a.js
/Users/mjr/app/node_modules/b/b.js
exports#
- <Oggetto>
Un riferimento almodule.exports
più breve da digitare.Vedere la sezione relativa al collegamento alle esportazioni per i dettagli su quando usare exports
e quando usaremodule.exports
.
modulo#
- <modulo>
Un riferimento al modulo corrente, vedere la sezione suimodule
oggetto., In particular, module.exports
is used for defining whata module exports and makes available through require()
.
require(id)#
-
id
<string> module name or path - Returns: <any> exported module content
Used to import modules, JSON
, and local files. Modules can be importedfrom node_modules
., Moduli locali e JSON file possono essere importati usinga percorso relativo (ad esempio ./
./foo
./bar/baz
../foo
) che beresolved contro la directory con il nome di __dirname
(se definito) ola directory di lavoro corrente. I percorsi relativi dello stile POSIX vengono risolti in modo indipendente dal sistema operativo, il che significa che gli esempi sopra funzioneranno su Windows nello stesso modo in cui funzionerebbero sui sistemi Unix.
require.cache
#
- <Object>
I moduli vengono memorizzati nella cache in questo oggetto quando sono necessari. Eliminando un keyvalue da questo oggetto, il successivo require
ricaricherà il modulo.Questo non si applica agli addon nativi,per i quali il ricaricamento comporterà un errore.
È anche possibile aggiungere o sostituire voci. Questa cache viene controllata prima dei moduli nativi e se un nome corrispondente a un modulo nativo viene aggiunto alla cache,non è più richiesta la chiamata per ricevere il modulo nativo. Usare con cura!,
require.extensions
#
- <Oggetto>
Istruire require
su come gestire determinate estensioni di file.
Elabora i file con estensione.sjs
come.js
:
require.extensions = require.extensions;
Deprecato. In passato, questo elenco è stato utilizzato per caricare non JavaScriptmodules nel nodo.js compilandoli su richiesta., Tuttavia, in pratica, ci sono modi molto migliori per farlo, come caricare i moduli tramite qualche altro Nodo.jsprogram, o compilarli in JavaScript prima del tempo.
Evitare di utilizzarerequire.extensions
. L’uso potrebbe causare bug sottili e la risoluzione delle estensioni diventa più lenta con ogni estensione registrata.
require.main
#
- <modulo>
Module
oggetto che rappresenta la voce script caricato quando il Nodo.jsprocess lanciato.,See “Accessing the main module”.
In entry.js
script:
console.log(require.main);
node entry.js
require.resolve(request)
#
Version | Changes |
---|---|
v8.9.0 |
The |
v0.3.0 |
Added in: v0.3.,0 |
-
request
<string> The module path to resolve. -
options
<Object>-
paths
<string> Paths to resolve module location from., Se presente, questi percorsi vengono utilizzati al posto dei percorsi di risoluzione predefiniti, con l’eccezione di GLOBAL_FOLDERS come$HOME/.node_modules
, che sono sempre inclusi. Ognuno di questi percorsi viene utilizzato come punto di partenza perl’algoritmo di risoluzione del modulo, il che significa che la gerarchianode_modules
è controllata da questa posizione.,
-
- Restituisce: <string>
interno require()
macchinari per cercare la posizione di un modulo,ma anziché il caricamento del modulo, restituzione risolto il nome del file.
Se il modulo non può essere trovato, viene generato un errore MODULE_NOT_FOUND
.
require.resolve.paths(request)
#
-
request
<string> Il percorso del modulo di cui la ricerca di percorsi di recupero., - Returns: <string> | <null>
Returns an array containing the paths searched during resolution of request
ornull
if the request
string references a core module, for example http
orfs
.
The module object#
- <Object>
In ogni modulo, la variabile liberamodule
è un riferimento all’oggetto che rappresenta il modulo corrente. Per comodità, module.exports
è accessibile anche tramite il modulo exports
-globale. module
in realtà non è globale ma piuttosto locale per ciascun modulo.
modulo.bambini #
- <modulo >
Gli oggetti modulo richiesti per la prima volta da questo.
modulo.esporta#
- <Oggetto>
L’oggetto module.exports
viene creato dall’oggetto Module
sistema. A volte questo non è accettabile; molti vogliono che il loro modulo sia un’istanza di qualche classe. Per fare questo, assegnare l’oggetto di esportazione desiderato a module.exports
., Assegnando l’oggetto desiderato a exports
sarà semplicemente rebind la variabile locale exports
, che probabilmente non è ciò che si desidera.
Ad esempio, supponiamo che stessimo creando un modulo chiamatoa.js
:
Quindi in un altro file potremmo fare:
const a = require('./a');a.on('ready', () => { console.log('module "a" is ready');});
L’assegnazione amodule.exports
deve essere eseguita immediatamente. Non può essere inserito in alcun callback., Questo non funziona:
x.js
:
setTimeout(() => { module.exports = { a: 'hello' };}, 0);
y.js
:
const x = require('./x');console.log(x.a);
exports
scorciatoia
exports
variabile è disponibile all’interno del modulo in un file a livello di ambito, e isassigned il valore di module.exports
prima che il modulo di valutazione.,
Quando module.exports
proprietà è stata completamente sostituita da un newobject, è comune anche riassegnare exports
:
module.exports = exports = function Constructor() { // ... etc.};
Per illustrare il comportamento, immagino che questo ipotetico attuazione delrequire()
che è molto simile a quello che è in realtà fatta da require()
:
modulo.filename#
- <string>
Il nome del file completamente risolto del modulo.
modulo.,id #
- <string>
L’identificatore per il modulo. In genere questo è completamente resolvedfilename.
modulo.isPreloading #
- Digitare:<booleano>
true
se il modulo è in esecuzione durante il Nodo.fase di precarico js.
modulo.caricato#
- <booleano>
Indipendentemente dal fatto che il modulo sia in fase di caricamento o meno.
modulo.parent #
require.main
emodule.children
invece.,- <modulo> | <null> | <undefined>
Il modulo che prima richiesta di uno o null
se il modulo corrente è theentry punto del processo corrente, o undefined
se il modulo è stato caricato bysomething che non è un CommonJS modulo (E. G.: REPL o import
).
modulo.percorso #
- <string>
Il nome della directory del modulo. Questo è di solito lo stesso delpath.dirname()
del module.id
.
modulo.percorsi #
- <string>
I percorsi di ricerca per il modulo.
modulo.richiedi (id) #
-
id
<string> - Restituisce: <qualsiasi> esportato il modulo contenuto
module.require()
metodo fornisce un modo per caricare un modulo come serequire()
è stato chiamato dal modulo originale.
Per fare ciò, è necessario ottenere un riferimento all’oggetto module
.,Poichérequire()
restituiscemodule.exports
emodule
è tipicamente disponibile solo all’interno del codice di uno specifico modulo, deve essere esplicitamente esportato per essere utilizzato.
L’oggetto Modulo#
Questa sezione è stata spostata su moduli:module
modulo principale.
module.builtinModules
module.createRequire(filename)
module.createRequireFromPath(filename)
module.syncBuiltinESMExports()