Node.js
Esportazione e consumo di moduli
Ricerca…
Osservazioni
Mentre tutto in Node.js viene generalmente eseguito in modo asincrono, require()
non è una di quelle cose. Poiché in pratica i moduli devono essere caricati solo una volta, si tratta di un'operazione di blocco e devono essere utilizzati correttamente.
I moduli vengono memorizzati nella cache dopo la prima volta che vengono caricati. Se si sta modificando un modulo in fase di sviluppo, sarà necessario cancellare la sua voce nella cache del modulo per poter utilizzare le nuove modifiche. Detto questo, anche se un modulo viene cancellato dalla cache del modulo, il modulo stesso non viene raccolto, quindi è necessario prestare attenzione per il suo utilizzo negli ambienti di produzione.
Caricamento e utilizzo di un modulo
Un modulo può essere "importato" o altrimenti "richiesto" dalla funzione require()
. Ad esempio, per caricare il modulo http
fornito con Node.js, è possibile utilizzare quanto segue:
const http = require('http');
Oltre ai moduli forniti con il runtime, è anche possibile richiedere i moduli installati da npm, ad esempio express. Se avevi già installato Express sul tuo sistema tramite npm install express
, potresti semplicemente scrivere:
const express = require('express');
Puoi anche includere moduli scritti da te come parte della tua applicazione. In questo caso, per includere un file denominato lib.js
nella stessa directory del file corrente:
const mylib = require('./lib');
Nota che puoi omettere l'estensione e si supporrà .js
. Una volta caricato un modulo, la variabile viene popolata con un oggetto che contiene i metodi e le proprietà pubblicati dal file richiesto. Un esempio completo:
const http = require('http');
// The `http` module has the property `STATUS_CODES`
console.log(http.STATUS_CODES[404]); // outputs 'Not Found'
// Also contains `createServer()`
http.createServer(function(req, res) {
res.writeHead(200, {'Content-Type': 'text/html'});
res.write('<html><body>Module Test</body></html>');
res.end();
}).listen(80);
Creazione di un modulo hello-world.js
Il nodo fornisce l'interfaccia module.exports
per esporre funzioni e variabili ad altri file. Il modo più semplice per farlo è esportare solo un oggetto (funzione o variabile), come mostrato nel primo esempio.
Hello-world.js
module.exports = function(subject) {
console.log('Hello ' + subject);
};
Se non vogliamo che l'intero export sia un singolo oggetto, possiamo esportare funzioni e variabili come proprietà dell'oggetto exports
. I tre esempi seguenti dimostrano tutto ciò in modi leggermente diversi:
- hello-venus.js: la definizione della funzione viene eseguita separatamente, quindi aggiunta come proprietà di
module.exports
- ciao-jupiter.js: le definizioni delle funzioni sono messe direttamente come valore delle proprietà di
module.exports
- hello-mars.js: la definizione della funzione viene dichiarata direttamente come una proprietà di
exports
che è una versione breve dimodule.exports
ciao-venus.js
function hello(subject) {
console.log('Venus says Hello ' + subject);
}
module.exports = {
hello: hello
};
Hello-jupiter.js
module.exports = {
hello: function(subject) {
console.log('Jupiter says hello ' + subject);
},
bye: function(subject) {
console.log('Jupiter says goodbye ' + subject);
}
};
Hello-mars.js
exports.hello = function(subject) {
console.log('Mars says Hello ' + subject);
};
Caricamento del modulo con il nome della directory
Abbiamo una directory chiamata hello
che include i seguenti file:
index.js
// hello/index.js
module.exports = function(){
console.log('Hej');
};
main.js
// hello/main.js
// We can include the other files we've defined by using the `require()` method
var hw = require('./hello-world.js'),
hm = require('./hello-mars.js'),
hv = require('./hello-venus.js'),
hj = require('./hello-jupiter.js'),
hu = require('./index.js');
// Because we assigned our function to the entire `module.exports` object, we
// can use it directly
hw('World!'); // outputs "Hello World!"
// In this case, we assigned our function to the `hello` property of exports, so we must
// use that here too
hm.hello('Solar System!'); // outputs "Mars says Hello Solar System!"
// The result of assigning module.exports at once is the same as in hello-world.js
hv.hello('Milky Way!'); // outputs "Venus says Hello Milky Way!"
hj.hello('Universe!'); // outputs "Jupiter says hello Universe!"
hj.bye('Universe!'); // outputs "Jupiter says goodbye Universe!"
hu(); //output 'hej'
Invalida della cache del modulo
In fase di sviluppo, potresti scoprire che l'uso di require()
sullo stesso modulo più volte restituisce sempre lo stesso modulo, anche se hai apportato modifiche a quel file. Questo perché i moduli vengono memorizzati nella cache la prima volta che vengono caricati e tutti i successivi carichi del modulo verranno caricati dalla cache.
Per ovviare a questo problema, dovrai delete
la voce nella cache. Ad esempio, se hai caricato un modulo:
var a = require('./a');
È quindi possibile eliminare la voce della cache:
var rpath = require.resolve('./a.js');
delete require.cache[rpath];
E quindi richiedi di nuovo il modulo:
var a = require('./a');
Si noti che questo non è raccomandato in produzione perché l' delete
cancellerà solo il riferimento al modulo caricato, non i dati caricati stessi. Il modulo non è garbage collection, quindi l'uso improprio di questa funzione potrebbe portare alla perdita di memoria.
Costruire i tuoi moduli
Puoi anche fare riferimento a un oggetto per esportare pubblicamente e aggiungere continuamente metodi a quell'oggetto:
const auth = module.exports = {}
const config = require('../config')
const request = require('request')
auth.email = function (data, callback) {
// Authenticate with an email address
}
auth.facebook = function (data, callback) {
// Authenticate with a Facebook account
}
auth.twitter = function (data, callback) {
// Authenticate with a Twitter account
}
auth.slack = function (data, callback) {
// Authenticate with a Slack account
}
auth.stack_overflow = function (data, callback) {
// Authenticate with a Stack Overflow account
}
Per utilizzare uno di questi, basta richiedere il modulo come faresti normalmente:
const auth = require('./auth')
module.exports = function (req, res, next) {
auth.facebook(req.body, function (err, user) {
if (err) return next(err)
req.user = user
next()
})
}
Ogni modulo iniettato una sola volta
NodeJS esegue il modulo solo la prima volta che lo richiedi. Ogni ulteriore richiesta di funzioni riutilizzerà lo stesso oggetto, quindi non eseguirà il codice nel modulo un'altra volta. Anche il nodo memorizza nella cache i moduli la prima volta che vengono caricati utilizzando require. Ciò riduce il numero di letture di file e aiuta a velocizzare l'applicazione.
myModule.js
console.log(123) ;
exports.var1 = 4 ;
index.js
var a=require('./myModule') ; // Output 123
var b=require('./myModule') ; // No output
console.log(a.var1) ; // Output 4
console.log(b.var1) ; // Output 4
a.var2 = 5 ;
console.log(b.var2) ; // Output 5
Caricamento del modulo da node_modules
I moduli possono essere require
d senza utilizzare percorsi relativi inserendoli in una directory speciale chiamata node_modules
.
Ad esempio, per require
un modulo chiamato foo
da un file index.js
, è possibile utilizzare la seguente struttura di directory:
index.js
\- node_modules
\- foo
|- foo.js
\- package.json
I moduli dovrebbero essere collocati all'interno di una directory, insieme a un file package.json
. Il campo main
del file package.json
dovrebbe puntare al punto di ingresso per il tuo modulo - questo è il file che viene importato quando gli utenti lo require('your-module')
. main
default index.js
se non previsto. In alternativa, è possibile fare riferimento a file in relazione al modulo semplicemente aggiungendo il percorso relativo alla require
chiamata: require('your-module/path/to/file')
.
I moduli possono anche require
d dalle directory node_modules
fino alla gerarchia del file system. Se abbiamo la seguente struttura di directory:
my-project
\- node_modules
|- foo // the foo module
\- ...
\- baz // the baz module
\- node_modules
\- bar // the bar module
saremo in grado di require
il modulo foo
da qualsiasi file all'interno della bar
usando require('foo')
.
Si noti che il nodo abbinerà solo il modulo più vicino al file nella gerarchia del filesystem, a partire da (la directory corrente del file / node_modules). Nodo corrisponde alle directory in questo modo fino alla radice del file system.
È possibile installare nuovi moduli dal registro di npm o altri registri di npm o crearne di nuovi.
Cartella come modulo
I moduli possono essere suddivisi su molti file .js nella stessa cartella. Un esempio in una cartella my_module :
function_one.js
module.exports = function() {
return 1;
}
function_two.js
module.exports = function() {
return 2;
}
index.js
exports.f_one = require('./function_one.js');
exports.f_two = require('./function_two.js');
Un modulo come questo viene utilizzato facendo riferimento ad esso dal nome della cartella:
var split_module = require('./my_module');
Si noti che se lo si richiede omettendo ./
o qualsiasi indicazione di un percorso di una cartella dall'argomento della funzione require, Node proverà a caricare un modulo dalla cartella node_modules .
In alternativa puoi creare nella stessa cartella un file package.json
con questi contenuti:
{
"name": "my_module",
"main": "./your_main_entry_point.js"
}
In questo modo non è necessario nominare il file del modulo principale "index".